作为复习计算机网络用,不记得了就过来看一看,写的时候也能发现一些问题
HTTP
超文本传输协议(HyperText Transfer Protocol)
协议: 两位或多位参与者为达到同一目的,约定的行为规范(租房协议)
传输: 从A点搬到B点,或者从B点搬到A点,是双向的
超文本: 指的是图片、文字、音视频等混合体,含有超链接,能从一个超文本跳转到另一个超文本
HTTP是计算机世界中专门在两点之间传送图片,文本等超文本数据的约定和规范
DNS
Domain Name System 域名系统,作用是把域名转换为网络层需要用到的IP地址。
并不代表域名没有用,HTTP/1.1的规范中,必须在请求头中携带Host头部,目的是当请求服务器有多台虚拟主机时,通过Host来明确是要请求哪个主机. 例如在一台服务器中有www.a.com, www.b.com, 如果只有一个IP地址,那么HTTP请求就不知道到底是请求a还是b了.
DNS三层结构
- 1 根域名服务器(Root DNS Server) 作用是管理顶级域名服务器,返回"com","cn"等顶级域名服务器的IP地址
- 2 顶级域名服务器(Top-level DNS Server) 管理各自域下的权威域名服务器, 例如com顶级域名服务器可以返回a.com的IP地址
- 3 权威域名服务器(Authoritative DNS Server) 管理自己域名下主机的IP地址, 比如a.com可以返回www.a.com的IP地址
DNS解析过程
从浏览器输入一个URL,并按下回车后,浏览器会提取出域名部分,例如www.a.com.
- 1 查找浏览器缓存, 如果浏览器有该域名的缓存结果,则直接返回,否则进入第二步
- 2 查找操作系统缓存,有则返回,没有就进入第三步
- 3 查找本机host文件,看是否有域名的映射,有则返回,没有就进入第四步
- 4 向本机的DNS服务器发起请求,根据本机的DNS服务器的配置,采取递归查询或迭代查询.
递归查询
- 1 本机DNS服务器向根域名服务器发起请求,(其实www.a.com === www.a.com.root, 但是root省略了),查询到顶级域名服务器(.com)的NS记录和IP地址
- 2 根域名服务器代替客户端向顶级域名服务器发起请求,也就是查询"a.com",这里获取到下一级域名(权威域名服务器)的NS记录和IP地址
- 3 顶级域名服务器根据IP地址向权威域名服务器发起请求,也就是查询"www.a.com", 这里获取到了IP地址返回给客户端
迭代查询
本机会有一个DNS服务器, 可以是静态的或者DHCP动态分配的,著名的如google的8.8.8.8 阮一峰大佬的DNS原理 DNS预解析 <link ref='dns-prefetch' href='www.a.com' >
https下开启,还需要加上下面这行
<meta http-equiv="x-dns-prefetch-control" content="on">
HTTP报文
HTTP/1.1报文采用ASCII编码,所以我们能直接看
HTTP报文的三大结构
- 1 起始行 描述请求的基本信息
- 2 首部 key-value详细说明报文
- 3 实体 实际传输的数据 http报文规定必须有header, 也就是起始行+首部,header后面必须有空行,空行后面被视为实体
起始行
请求行
- 1 请求方法
- 2 请求URI
- 3 协议版本号 例如 Get / HTTP/1.1
URI (uniform Resource Identifier)统一资源标识符,唯一的标识一个资源
URL (Uniform Resource Locator)统一资源定位器,通过地址标识一个资源
URN (Uniform Resource Name) 统一资源名称,通过名字标识一个资源
URI = URL + URN, 所以URL是URI的子集,但是现在很少人用URN了,所以大多时候URI = URL
状态行
- 1 版本号
- 2 状态码
- 3 原因短语 例如 HTTP/1.1 200 OK
头部
- 1 通用头部 请求报文和响应报文都可以加入
- 2 实体头部 描述实体的信息
- 3 请求头: 出现在请求头中
- 4 响应头: 出现在响应头中
请求头
- 1 Accept: 浏览器可以接收的MIME Type,也就是能接受实体的数据类型,例如text/html
- 2 Accept-Encoding: 客户端支持的压缩格式, 例如gZip,deflate,br
- 3 Accept-Language: 客户端支持的自然语言, 例如zh-Cn,en
- 4 Accept-chartset: 客户端支持的编码格式, 例如utf-8
- 5 User-agent: 用户代理,常用来判断PC端还是移动端
- 6 Host: 域名,标明请求的是哪台主机,一台服务器可能有多个虚拟主机
- 7 ........
请求头中还有通过q表示权重,例如 Accpet-Language: zh-Cn;q=0.9,en;q=0.8
q越大,越倾向于获取这种资源,上面就是更希望获得简体中文的资源
注意不同的内容通过" , "分开,表示权重则用" ; "分开, HTTP中"," 比 " ; "断句意义大
响应头
- 1 Expires 一个日期,浏览器根据它判断是否使用强缓存, 优先级低于Cache-control
- 2 Date 响应报文的创建时间, cache-control中的max-age需要用到这个头部中的时间
- 3 Location 重定向地址
- 4 Set-Cookie 设置Cookie
- 5 Content-Type 表示报文中的实体数据的MIME Type
- 6 Content-Length 表示报文中实体数据的长度,有该头部则是定长包体,否则为不定长包体
定长包体和不定长包体
在说定长包体和不定长包体前要了解一下短连接和长连接.
长连接和短连接
在以前HTTP请求中,采用的是短连接,就是一次请求响应后立刻关闭TCP连接,这样会造成浪费。因为TCP连接会经过三次握手和四次挥手,效率低下。
HTTP/1.1中默认采用的长连接,也就是在第一次请求中建立TCP连接,在最后一次响应中断开TCP连接.
通过HTTP头部中的Connection: keep-alive表示使用长连接,可以使用Connection: close断开TCP连接.
问题,什么时候我知道要断开TCP连接了呢?难道TCP连接一直要占用内存吗?
- 1 通过配置,在多久没有请求后,也就是timeout时间,超时了就断开TCP连接
- 2 配置最大请求次数,即请求多少次后就断开连接。 上面这些方法要在一个前提下,那就是客户端的请求都已经结束了。那怎么知道一个响应已经发送完毕了呢? 答案是通过Content-Length标识传输的数据大小,传送了这么多数据,代表我传完了。
问题,如果传一个大文件,那服务端要把这个文件全部读取完我再传吗?
等到大文件都读取完了,客户端等的时间会有点久,那就边传边读,那怎么表示我传输完了大文件呢?
那就通过Transfer-Encoding: chunked表示我传输的是数据的一块,还没有传完.在最后一个chunked中通过0CRLF表示分段传输结束了
分块传输:
分块传输必须配合长连接一起使用。
Transfer-chunked和Content-Length是互斥的,只会出现某一个
范围请求
问题: 当我们看视频时,想要跳过片头,通过拖动进度条就可以完成,实际是发出了一个范围请求,请求某一部分的资源.
例如上面的If-Range是一个条件请求,Range: bytes=2564417-2761944如果支持范围请求,则返回206和部分资源,如果不支持范围请求就返回200 OK和整个资源,如果范围请求超过资源大小,则返回416状态码
判断服务器是否支持范围请求
通过发送一个HEAD请求,如果响应头出现了Accept-Ranges: bytes表示支持范围请求,同时还可以获取文件的大小
发起范围请求
需要在请求头中加入Range: bytes=x-y
x-y表示偏移量,表示要获取哪一段资源
服务器处理范围请求
- 1 检查范围请求是否合法,如果只有200字节的数据,但要请求400-500字节的数据,那么服务器就会返回416,表示范围请求有误
- 2 如果范围正确,那么服务器会在响应头中加入Content-Range: bytes x-y/length,读取资源的片段,返回206状态码,表示body是原资源的一部分
多段数据
上面的只能获取一个片段,但它还可以支持一次获取多个片段数据。
需要通过一个特殊的MIME Type就是multipart/byteranges,并且还有一个分隔符boundary=xxx
例如
GET /16-2 HTTP/1.1
Host: www.chrono.com
Range: bytes=0-9, 20-29
响应
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=00000000001
Content-Length: 189
Connection: keep-alive
Accept-Ranges: bytes
--00000000001
Content-Type: text/plain
Content-Range: bytes 0-9/96
// this is
--00000000001
Content-Type: text/plain
Content-Range: bytes 20-29/96
ext json d
--00000000001--
最后以--00000000001--,注意两边都有--
分段传输和范围请求的区别
范围请求是请求某一部分资源
分段传输是服务器无法第一时间知道要传输资源的大小,通过边读边传的方式,免得客户端等太久,最后通过0CRLF表示分段传输结束
浏览器缓存
合理利用浏览器缓存是减少网络请求,缓解服务器压力的好办法。
服务器缓存
通过响应头可以知道服务器对于该资源客户端是否可以缓存,缓存多久
Cache-control
- 1 max-age: 30s 表示客户端可以缓存这个资源30s,30s内如果有请求这个资源,那么直接发给他就好了,计算方式(与响应报文的创建时间相关,也就是响应头中的Date字段,从那时间过30s后,这个资源就失效了,所以资源也有可能传输过程中就失效了)
- 2 no-store: 不允许缓存,每次请求都去源服务器
- 3 no-cache:可以缓存,但是使用之前必须要跟源服务器验证是否过期了(如果有Last-modified或者ETag就走协商缓存,不然就是直接获取新资源,不适用缓存了)
- 4 must-revalidate: 如果没有过期你就用继续用,如果过期了就必须跟源服务器确认资源是最新的
网页F5刷新,相当于Cache-Control: max-age=0
ctrl+F5刷新,相当于Cache-Control: no-cache
不知道他两有什么区别,有大佬可以告知我一下
Expires
值是一个日期和时间,与系统的时间比较,不太准,优先级低于Cache-Control.
ETag
ETag是一个实体标签,是资源的唯一标识,使用ETag可以准确地识别资源的变动情况。
ETag有 “强”“弱” 之分
强 ETag 要求资源在字节级别必须完全相符,弱 ETag 在值前有个“W/”标记,只要求资源在语义(功能上)上没有变化,但内部可能会有部分发生了改变(例如 HTML 里的标签顺序调整,或者多了几个空格)
例子:
- 强ETag, 客户端有一个10字节的数据,服务器相同的数据加了一个无意义空格,客户端也不要原来的,一定要新的。
- 弱Tag,多一个空格也一样
Last-modified
文件的最后修改时间,优先级低于ETag,有ETag就忽略它了
max-stale
资源过期多久后,我还能直接使用缓存
min-fresh
例如min-fresh: 10,如果还有8s这个资源就过期了,那么就不使用缓存了,有效期必须大于10s才使用缓存
条件请求
条件请求的意思是如果满足了我的条件,服务器才处理,不满足我的条件就直接回复304 Not modified了
- 1 "If-Modified-Since",如果资源从这个日期开始有更改,服务器就处理这个请求,否则就回复304,这个日期是相同请求URL中的响应头的Last-Modified
- 2 "If-None-Match", 如果服务器没有匹配到有这个标识的资源,服务器就处理这个请求,否则回复304
条件请求就是协商缓存了
tip:如果没有Cache-Control和Expires,但是有Last-modifed,浏览器会使用max-age=(Date - Last-Modified) * 10%强行使用强缓存.
代理服务器缓存
Cache-control
- public 谁都可以缓存资源
- private 不允许代理服务器缓存资源
- s-maxage 类似与max-age,但作用于代理服务器
代理服务器
代理分为4种
- 匿名代理: 完全“隐匿”了被代理的机器,外界看到的只是代理服务器
- 透明代理: 顾名思义,它在传输过程中是“透明开放”的,外界既知道代理,也知道客户端
- 正向代理: 靠近客户端,代表客户端向服务器发送请求
- 反向代理: 靠近服务器端,代表服务器响应客户端的请求
代理的作用
- 负载均衡:将请求分散到多台机器,实现访问集群化
- 内容缓存:代替源服务器返回响应
- 安全防护:保护被代理的机器
- 数据处理:提供压缩、加密等额外功能
- 健康检查:通过心跳等机制监控后端服务器,如有故障则踢出集群
代理的字段
- Via: 每经过一次代理节点,就会把代理服务器自己的信息加入到字段的末尾
- X-Forwarded-For:每经过一个代理节点,包括客户端,会把自身的IP加入到末尾
- X-Real-IP: 获取客户端真实的IP
代理协议
通过 X-Forwarded-For来附加信息,必须要解析HTTP报文,但是HTTPS怎么解析呢,这就提高了转发的成本。所以有了代理协议
通过开头加入PROXY IP地址类型 请求方地址 目标地址 请求端口号 目标端口号
例如 PROXY TCP4(TCP6) 1.1.1.1 2.2.2.2 55555 80\r\n
PROXY TCP4 1.1.1.1 2.2.2.2 55555 80\r\n
GET / HTTP/1.1\r\n
Host: www.xxx.com\r\n
\r\n
HTTPS
HTTPS是在HTTP的基础上加上SSL/TLS层,以前是HTTP Over TCP/IP,那么HTTPS就是HTTP Over SSL/TLS,当然底层还是要借助TCP的.
我们从问题说起,HTTP存在一些问题
- 传输的数据是明文的,容易被别人监听到
- 传输的数据可能会被篡改,客户端并不知道数据是否完整
- 浏览器并不知道这个响应是否是真正的服务器发过来的,身份有待考证
如何解决这些问题呢
我先说答案,再来看HTTPS是怎么保证安全的。
数据的明文问题,采用对称加密和非对称加密结合使用来加密数据传输。
数据的完整性问题,采用摘要算法生成摘要,摘要算法是通过哈希函数或者散列函数来完成
怎么保证通信方的身份,通过数字签名,非对称加密中有公钥和私钥(下面有讲),因为私钥是私密的,只有跟你通信的那个人知道,你能用公钥解开,那么就能确保身份
看不懂别怕,我们一点点来看
为什么采用对称加密和非对称加密混合加密的方式呢?
我们得先说一下对称加密和非对称加密
对称加密
对称加密是通过一个会话密钥来对数据进行加解密
就是双方通过一个钥匙来打开数据,那么问题就是,每天都很多客户端来请求,我怎么把这个钥匙秘密的给他们呢?最后发现,无论怎么发,都会被有心人拿到,只通过对称加密是无法完成加密的.常见的对称加密算法:AES,CHACHA20,接着来看看非对称加密吧
非对称加密
- 非对称加密是服务器生成一对密钥,有公钥和私钥之分,公钥加密的数据必须得私钥解开,公钥解不开
- 私钥加密得数据必须公钥解开,服务器必须得保管好私钥不能被别人知道了.公钥则可以四处给别人
- 这样子,服务器和客户端都持有一套公钥和私钥,如果你要发信息给我,就用我的公钥加密,我再用我的私钥解密,这样子可以保证双方的通信是安全的
- 常见ECDHE、RSA算法,它们两个在TLS握手上会有所不同,后面再说 但是这样就一定安全了吗?
- 1、客户端怎么知道他拿到的公钥一定是服务器的?中间人把公钥替换成他自己的,客户端用他的公钥加密,他用他的私钥解开,就获得客户端的信息了.
- 2、非对称加密算法速度很慢,差了对称加密大概几百倍,对于用户来说,太痛苦了,等那么久 针对非对称算法加解密太复杂导致速度很慢,所以采用加密速度很快的对称加密和非对称加密结合来加密数据,问题1后面再说,有关身份认证
TLS1.0 等于 SSL3.0
完整性
到此实现了数据的加密,现在我们来看看如何实现完整性,在此需要引入摘要算法
摘要算法
摘要算法可以理解成特殊的压缩,把一串长数据压缩成固定长度,独一无二的字符串,且是单向,不可逆转的,没有密钥可以解开,哪怕你在原数据改了一个标点符号,再生成的摘要也是完全不同的。
常见的摘要算法:MD5,SHA-1,SHA-2
只要我们通过数据生成一个独一无二的摘要,并把它附加到原文后面,客户端接收到了之后,也根据这个算法算一样,如果两个一模一样,那这个数据就是完整的,如果不一样,直接丢掉,因为被别人篡改过了。
如果明文传输摘要,中间人可以直接把数据替换了,自己生成一个摘要,客户端再生成一次也是一样的,这样是不安全的,所以要保证机密性来传输摘要,这样才能保证数据完整性
数字签名
现在来解决第三个问题,怎么完成身份验证,那就是通过数字签名
现实生活中,公司的身份认证是咋样的,就是通过盖一个章或者签一个名来完成的。
在这里我们也能通过签名来完成身份认证。
- 服务器通过私钥加密数据,如果用服务器的公钥解开了密文,那么这就是服务器发来的消息
- 那用私钥加密什么数据呢?数据太多会很慢,于是就聪明的人就通过私钥加密摘要,完成身份认证
- 这样子数字签名就完成了完整性和身份认证两个问题
数字证书
回到上面的问题,客户端怎么知道他拿到的公钥一定是服务器的?,因为就算服务器用私钥加密了会话密钥,中间人也可以直接替换掉整个加密信息,用中间人自己的私钥加密数据发给客户端,这样实际上就是在跟中间人通信,那怎么保证拿到的公钥一定是服务端的呢?这就要引入CA机构了
CA(Certificate Authority,证书认证机构)
它就像现实世界中的警察局,是完全可以信任的,你也必须信任它,否则无法进行下去了,由它来给公钥签名,这样就可以保证公钥是来自服务器的了,系统内置了可信任CA机构的证书
服务器先把公钥提交给CA机构,CA机构再把序列号、用途、颁发者、有效时间等等打成一个包再签名,形成数字证书。证书主要包含两个东西,数字签名和服务器公钥
服务器在TLS握手中,发送数字证书给客户端,客户端会根据系统内置的CA公钥来解密报文,获得服务器公钥和数据摘要,再根据摘要算法,算一遍数据的摘要,跟解密出来的数据摘要是否一致,一致则表示拿到的就是服务端的公钥。
TLS握手
接下来看看TLS握手是怎样的
- 客户端和服务端进行TCP三次握手,建立连接
- 客户端发送Client Hello,里面包含密码套件,一个随机数Client_Random,使用的协议版本号如TLS1.2。
- 服务端发送Server Hello,里面包含服务器选择的密钥套件,一个随机数Server_Random,版本号,发送给客户端
- 服务端发送数字证书证明身份.
- 如果密钥交换采取的是ECDHE算法,(不是就跳过)那么服务器发出Server key Exchange,表示交换密钥交换算法的公钥,用ECDHE算法一顿算,得到一个Server Params(用来生成后面的pre_master,per_master是用来生成最后一个随机数的,要绝对保密的),也就把这个Server Params,生成摘要,用私钥加密发给客户端
- 服务器发送Server Hello Done表示打招呼结束了
- 客户端收到服务器的数字证书,用上面说过的方法校验,确保是跟服务器通信,同时拿到公钥,接下来根据ECDHE算法一顿算,也算出一个密钥交换的公钥Client Params,生成摘要,用证书得到的公钥加密后,发给服务器,也就是发出Client Key Exchange
- 服务器收到Client Key Exchange后,用自己的私钥解开报文,得到客户端给它的用于密钥交换的公钥,此时服务器有一个自己根据密钥交换算法的私钥,和客户端给的公钥,咔咔一顿算,算出来一个预主密钥Pre_Master。根据前面的Client_Random,Server_Random,Pre_Master,咔咔一顿算,算出来一个会话密钥,可以用于加密数据,而且是保密的
- 客户端再发出Client Key Exchange后,跟服务器同样的步骤,根据Client_Random,Server_Random,Pre_master算出一模一样会话密钥,这样,客户端和服务端都有会话密钥
- 之后客户端继续发出Change Cipher Spec,和一个Finished报文,把之前发送的信息做个摘要,再加密一下,发给服务器,主要是验证一下算出来的密钥对不对,大家是不是都一样。如果一样后面就直接加密通信了。
- 服务器也发出Change Ciper Spec 和 Finished报文,这样双方都验证了加解密OK,就用加密通信了
- 到此完成了HTTPS的安全保障。
有关于密钥交换
前面所说非对称加密主要保障的就是Pre_Master的安全交换,Pre_Master是生成会话密钥的关键,必须安全交付,服务器和客户端都会根据密钥交换算法ECDHE算法算出来一个公钥和一个私钥,公钥发给对方。收到对方的公钥之后,根据ECDHE算法直接算出来Pre_Master,再用之前的Client_Random,Server_Random,Pre_Master生成会话密钥,这个Pre_Master是由算法保证,很难被别人猜测到的,(RSA算法则不是这样,RSA算法是直接由客户端再生成一个随机数,用证书得到的公钥加密后发给服务器,但是RSA不具有前向安全性)
1 - Client Hello
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Random: 1cbf803321fd2623408dfe…
Cipher Suites (17 suites) //密码套件
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
密码套件
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- ECDHE 表示密钥交换算法,别的还有RSA...
- RSA 表示加密摘要的算法,完成身份认证
- AES_128 使用AES的对称加密算法,密钥长度为16bytes
- GCM 分组模式,用固定长度的密钥加密任意长度的数据,表示如何分组加密
- SHA256 摘要算法,把数据压缩成一段字符串,微小的不同生成的HASH是完全不一样的。
2 - Server Hello
Handshake Protocol: Server Hello
Version: TLS 1.2 (0x0303)
Random: 0e6320f21bae50842e96…
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
3 - Key Exchange
Handshake Protocol: Server Key Exchange
EC Diffie-Hellman Server Params
Curve Type: named_curve (0x03)
Named Curve: x25519 (0x001d)
Pubkey: 3b39deaf00217894e...
Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
Signature: 37141adac38ea4...
TLS1.3
区分TLS1.2和TLS1.3,通过Extension扩展协议和supported_versions来标记使用TLS1.3
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Extension: supported_versions (len=11)
Supported Version: TLS 1.3 (0x0304)
Supported Version: TLS 1.2 (0x0303)
强化安全
废除了一些有漏洞和漏洞的加密算法,只剩下5种
前向安全
如果加密系统使用服务器证书里的RSA 做密钥交换,一旦私钥泄露或被破解(使用社会工程学或者巨型计算机),那么黑客就能够使用私钥解密出之前所有报文的“Pre-Master”,再算出会话密钥,破解所有密文。当前的密钥被破解,会影响到之前所有的通信。
而 ECDHE 算法在每次握手时都会生成一对临时的公钥和私钥,每次通信的密钥对都是不同的,也就是“一次一密”,即使黑客花大力气破解了这一次的会话密钥,也只是这次通信被攻击,之前的历史消息不会受到影响,仍然是安全的。
1-RTT
TLS1.2的握手需要经过2个RTT,TLS1.3压缩了握手过程,把握手时间减少到了1-RTT.
- 客户端在"Client Hello"直接用support_groups带上支持的曲线,用key_share带上曲线对于的客户端公钥参数(Client_Param),用signature_algorithms带上签名算法
- 服务端Server Hello照样返回选择的密码套件,一个随机数和版本号,虽然再加上key_share,也就是Server_Param,这样子就能直接拿到Client Random和Server Random、Client Params和Server Params就可以直接算出会话密钥了,只需要1个RTT
- 服务器算出会话密钥后,直接就发送Change Cipher Spec,后面就进入加密通信了,后面发送证书都是加密过的了
- 客户端再回一个Change Ciper Spec和Finished,不用等回复,直接就开始加密通信了
另外的性能优化
- Session ID:客户端保存一个ID,连接时发送给服务端,服务端内存里存储主密钥和其他相关的信息,跳过证书验证和密钥交换,压力在服务端
- Session Ticket:存储压力转移到客户端,客户端使用扩展“session_ticket”发送“Ticket”而不是“Session ID”,服务器解密后验证有效期,就可以恢复会话,开始加密通信。
- PSK: 验证阶段把数据也带上,少一次请求,实现0-RTT
HTTP/2
HTTP2基于Google的SPDY协议,
头部压缩
HPACK
HPACK是专门为了压缩头部数据产生的算法,在客户端和服务端两端建立字典,用索引号表示重复的字符串,还采用哈夫曼编码来压缩整数和字符串,可达到50%-80%的高压缩率。
二进制分帧
HTTP/1中使用的是ASCII编码,而HTTP/2则把原来header+body的消息打散为数个二进制帧,用HEADERS帧存放头数据,用DATA帧存放数据
虚拟的流
多个帧到达目的地之后怎么拼接起来呢?HTTP/2采用了流的概念,它是二进制帧的双向传输序列,同一个消息的帧带上同一个流ID,同一个流的数据帧按照顺序组装起来,就是HTTP/1中的请求/响应报文.所以HTTP/2可以在同一个TCP连接中,同时发送多个帧,这就是多路复用.
对于流来说,消息是有序的帧,但相对于TCP连接来说,消息是乱序收发的帧,多个请求/响应没有了顺序,不需要排队等候,也就没有了队头阻塞。
另外还可以通过控制帧来调整请求响应的优先级
HTTP/2连接前言
HTTP/2必须基于SSL/TLS之上,在TLS握手完成后,客户端需要发送一个连接前言,使用HTTP/1的请求报文方式,请求方法是特别的关键字PRI
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n
服务端收到这个请求后就知道客户端想要使用HTTP/2西医
HTTP/2准备请求报文
首先第一步是压缩头部,HPACK是专门为压缩HTTP头部定制的算法,是客户端和服务端共同维护一份索引表,压缩和解压缩就是查表和更新表的操作。
HTTP/2废除了起始行的概念,引入了伪头字段,例如:authority表示域名,:method表示请求方法,:status表示状态码。
这些常见的头字段在一个静态表中,例如数字2表示GET
但是自定义字段怎么办呢,这就要用到动态表,它添加到静态表后面,会随着HTTP/2报文的越来越多,也会越来越完善,最终每次头部都会变成几个字节。
二进制帧
头部压缩好了之后,HTTP/2就把报文拆成二进制帧发送。
HTTP/2帧结构
我是一个非科班的菜鸟,如果有不对请指出,感谢您的阅读
如果可以,点个赞吧,感激不尽( ^-^ )
还没有写完,晚点再更新了