xiaolin coding 图解网络笔记——HTTP篇
1. HTTP 是什么?
HTTP 是超文本传输协议(HyperText Transfer Protocol),一个用在计算机世界里专门在【两点】之间【传输】文字、图片、音频、视频等【超文本】数据的【约定和规范】。
2. HTTP 常见的状态码有哪些?
1xx
类状态码属于提示信息,是协议处理中的一种中间状态
2xx
类状态码表示服务器成功处理了客户端的请求:
200 OK
是最常见的成功状态码,表示一切正常。204 No Content
也是常见的成功状态码,与200 OK
基本相同,但响应头没有 body 数据。206 Partial Content
是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。
3xx
类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
301 Moved Permanently
表示永久重定向,说明请求的资源已经不存在了。302 Found
表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
301 和 301 都会在响应头里使用字段Location
,指明后需要跳转的 URL。304 Not Modified
不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向。
4xx
类状态码是错误码,表示客户端发送的报文有误,服务器无法处理。
400 Bad Request
表示客户端请求的报文有错误,但只是个笼统的错误。403 Forbidden
表示服务器禁止访问资源,并不是客户端的请求出错。404 Not Found
表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx
类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务端的错误码。
500 Internal Server Error
与 400 类型,是个笼统通用的错误码,服务器发生了什么错误并不知道。501 Not Implemented
表示客户端请求的功能还不支持。类似“即将开业,敬请期待”。502 Bad Gateway
通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。503 Service Unavailable
表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”。
3. HTTP 常见字段有哪些?
Host
字段:客户端发送请求时,用来指定服务器的域名
Host: www.A.com
Content-Length
字段:服务器在返回数据时的字段,表明本次回应的数据长度
Content-Length: 1000
,在数据长度以后的字节就属于下一个回应。
HTTP 协议通过设置回车符、换行符作为 HTTP header 的边界,通过 Content-Length 字段作为 HTTP body 的边界,这两个方式都是为了解决 TCP 传输协议的“粘包”问题(TCP协议进行数据传输时,接收方在读取数据时,一次读取了多个数据包的内容,因为TCP会对数据包进行分割,是流式传输,所以需要明确边界)。
Connection
字段:最常用于客户端要求服务器使用【HTTP 长连接】机制,以便其他请求复用。
HTTP 长连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。
Connection: Keep-Alive
,这是为了兼容老版本的 HTTP。
-
Content-Type
字段:用于服务器回应时告知客户端本次数据格式。
Content-Type: text/html; Charset=uft-8
-
Accept
字段:客户端请求时声明自己可以接受哪些数据格式。
Accept: */*
-
Content-Encoding
字段:说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。
Content-Encoding: gzip
-
Accept-Encoding
:客户端请求时说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate
4. GET 和 POST 有什么区别?
GET 的语义是从服务器获取指定的资源,GET 请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII。
POST 的语义是根据请求负荷(报文 body)对指定的资源作出处理,body 中的数据可以是任意格式的数据,而且浏览器不会对 body 大小做限制。
5. GET 和 POST 方法都是安全和幂等的吗?
- 在 HTTP 协议里,所谓的【安全】是指请求方法不会【破坏】服务器上的资源。
- 所谓的【幂等】,意思是多次执行相同的操作,结果都是【相同】的。
从 RFC 规范定义的语义来分析,几乎所有的互联网标准都收录在RFC文件中
- GET 方法是安全且幂等的,因为它是【只读】操作,并且方法是可被缓存的。
- POST 不安全,不幂等,大部分实现不可缓存,因为是【新增或提交数据】的操作,会修改服务器上的资源,浏览器一般不会缓存 POST 请求。
- 实际过程中,开发者不一定会规范定义,如果用 GET 实现增删数据,那么就是不安全不幂等的,如果用 POST 实现查询,那么 POST 就是安全和幂等的。
HTTP 传输的内容都是明文的,只要抓包都能看到,要避免传输过程中数据被窃取,就要使用 HTTPS 协议,这样所有 HTTP 的数据都会被加密传输。
6. HTTP 缓存有哪些实现方式?
对于一些具有重复性的 HTTP 请求,就可以把这对【请求-响应】的数据都缓存在本地,HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存。
7. 什么是强制缓存?
强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否缓存的主动性在于浏览器。
强缓存利用这两个 HTTP 响应头部(Response Header)字段实现,都用来表示资源在客户端缓存的有效期:
Cache-Control
,是一个相对时间Expires
,是一个绝对时间
如果 HTTP 响应头部同时有这两个字段,Cache-Control 的优先级高于 Expires。
具体流程如下:
- 当浏览器第一次请求服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,设置了过期时间大小;
- 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器。
- 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。
8. 什么是协商缓存?
某些请求的响应码是304
,这个是告诉浏览器可以使用本地缓存的资源,协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。
协商缓存可以基于两种头部来实现。
第一种:请求头部中的 If-Modified-Since
字段与响应头部中的 Last-Modified
字段实现,Last-Modified
标示这个响应资源的最后修改时间,请求头的If-Modified-Since
是当资源过期时,发现响应头具有Last-Modified声明,则再次请求时带上这个时间,服务器收到请求后将其与被请求资源的最后修改时间进行对比(Last-Modified
),如果最后修改时间较新,则返回最新资源,HTTP 200 OK
,如果较旧,说明资源无新修改,响应 HTTP 304
走缓存。
第二种:请求头部中的 If-None-Match
字段与响应头部中的 ETag
字段。响应头部中的ETag
是唯一标识响应资源,请求头部中的If-None-Match
是指当资源过期时,浏览器发现响应头里有ETag
,则再次向服务器发起请求时会将请求头If-None-Match
设置为 ETag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果变化了返回 200。
ETag 的优先级更高,因为可能文件内容没有改变但是最后修改时间改变了,有些文件是秒级内修改的,而 If-Modified-Since
检查的粒度是秒级的,Etag
的粒度更小,并且某些服务器不能精确获得文件的最后修改时间。
协商缓存这两个字段都需要配合强制缓存中的 Cache-Control 字段来使用,只有在未命中强制缓存的时候,才能发起带有协商缓存字段的请求。
9. HTTP/1.1 的优点有哪些?
HTTP 最突出的优点是【简单、灵活和易于扩展、应用广泛和跨平台】。
- 简单:HTTP 基本的报文格式就是
header + body
,头部信息也是key-value
简单文本的形式。 - 灵活和易于扩展:HTTP 协议里的各类请求方法、URI/URL(URI是统一资源标识符,提供了一种抽象的资源标识方式,可以用于不同的上下文和协议;URL 提供了一种具体的资源定位方式,允许用户或程序通过它来访问资源。)、状态码、头字段等每个组成要求都允许开发人员自定义和扩充。
由于 HTTP 是工作在应用层,则它下层可以随意变化,比如:
-
HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层;
-
HTTP/1.1 和 HTTP/2.0 传输协议使用的是 TCP 协议,而到了 HTTP/3.0 传输协议改用了 UDP 协议。
-
应用广泛和跨平台:HTTP 的应用广泛,同时天然具有跨平台的优越性,这是因为设计时就考虑了不同操作系统和平台的互操作性。
10. HTTP/1.1 的缺点有哪些?
HTTP 有优缺点一体特点,分别是【无状态、明文传输】,同时还有一个缺点【不安全】。
-无状态:无状态的好处是服务器不会去记忆 HTTP 的状态,不需要额外的资源记录状态信息,减轻服务器的负担,而坏处就是在完成有关联性的操作时会非常麻烦,例如登录->添加购物车->下单->结算->支付,这系列操作服务器不知道这些请求有关联,每次都要问一遍身份信息。
对于无状态的问题,最简单的方式用 Cookie 技术。
Cookie
通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。相当于,在客户端第一次请求后,服务器会下发一个装有客户信息的小贴纸,后续客户端请求服务器的时候,带上小贴纸,服务器就能直接认出。
-
明文传输:明文传输使得在传输过程中的信息方便阅读,为调试工作带来了便利,但是信息的内容毫无隐私很容易就被窃取。
-
不安全:HTTP 比较严重的缺点就是不安全:通信使用明文,内容可能会被窃听;不验证通信方的身份,有可能遭遇伪装;无法证明报文的完整性,有可能已遭篡改。
HTTP 的安全问题,可以用 HTTPS 的方式解决,也就是通过引入 SSL/TLS 层,使得在安全上达到了极致。
11. HTTP/1.1 的性能如何?
HTTP 协议是基于 TCP/IP,并且使用了请求-应答的通信模式,所以性能的关键就在这两点。
- 长连接:早期的 HTTP/1.0 每发起一次请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,增加了通信开销。为了解决这个问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开造成的额外开销,减轻了服务器端的负载。
持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。如果某个 HTTP 长连接超过一定时间没有提交任何数据交互,服务端就会主动断开这个连接。
- 管道网络传输:HTTP/1.1 采用了长连接的方式,这使得管道(pipeline)网络传输成为了可能。
即可在同一个 TCP 连接里面,客户端可以发起多个请求,后面的请求不必等前面的响应回来,可以减少整体的响应时间。
但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应,如果服务端在处理 A 请求时耗时比较长,那么后续的请求的处理都会被阻塞住,这称为【队头阻塞】。
所以,HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞。
(HTTP/1.1 管道化技术不是默认开启,有这个功能,但是没有被使用)
- 队头阻塞:当顺序发送的请求序列中的一个请求因为某种原因被阻塞,会导致客户端一直请求不到数据,这就是【队头阻塞】。所以 HTTP/1.1 性能一般。
12. HTTP 与 HTTPS 有哪些区别?
HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 应用层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
HTTP 连接建立相对简单,TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
两者的默认端口不一样,HTTP 默认端口号是80,HTTPS 默认端口号是443.
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
13. HTTPS 解决了 HTTP 的哪些问题?
通过信息加密解决窃听风险,通过校验机制解决篡改风险,通过身份证书解决冒充风险。
HTTPS 是如何解决上面的三个风险的?
- 混合加密:HTTPS 采用对称加密和非对称加密结合的混合加密方式:
- 在通信建立前采用非对称加密的方式交换【会话密钥】,后续就不再使用非对称加密。
- 在通信过程中全部使用对称加密的【会话密钥】的方式加密明文数据。
采用【混合加密】的方式的原因是:
- 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
- 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题,但速度慢。
相当于是使用非对称加密确保密钥的安全交换,服务器生成一对公钥和私钥,公钥可以安全的分发给任何客户端,私钥保密,然后客户端生成随机的会话密钥,并用服务器的公钥加密,发送给服务器,由于只有服务器有对应私钥,所以只有服务器能解密获得会话密钥。而对称加密用于数据加密,会话密钥安全的交换完成后,就可以使用更快的对称加密。
- 摘要算法 + 数据签名:为了保证传输的内容不被篡改,需要对内容计算出一个哈希值,然后同内容一起传输给对方。
对方收到后,先是对内容也计算出一个哈希值,然后跟发送方发送的哈希值做一个比较,如果相同,表示内容没有被篡改,在计算机里用摘要算法(哈希函数)来计算出内容的哈希值,这个哈希值是唯一的,且无法通过哈希值推导出内容。
通过哈希算法可以确保内容不会被篡改,但是并不能保证【内容 + 哈希值】不会被中间人替换,因为这里缺少对客户端收到的消息是否来源于服务端的证明。
这种情况就需要数字签名算法,非对称算法的公钥和私钥可以双向加解密,流程不同目的也不同,公钥加密,私钥解密是为了保证内容传输的安全,只有持有私钥的人才能解密出实际的内容;私钥加密,公钥解密是为了保证不会被冒充,证明这个消息来源于持有私钥身份的人发送的,
数字签名算法就是通过【私钥加密,公钥解密】,对内容的哈希值加密,来确认消息的身份。
私钥是由服务端报关,然后服务端会向客户端办法对应的公钥。如果客户端收到的消息能被公钥解密,说明该消息是由服务器发送的。
- 数字证书:前面可以知道,可以通过哈希算法保证消息的完整性,通过数字签名来保证消息的来源可靠性,但是还缺少身份验证的环节,万一公私钥都是被伪造的,所以数字证书相当于被公证的公钥,为了确保公钥的真实性和所有权,通过权威机构 CA (数字证书认证机构),将服务器公钥放在数字证书中,只要证书是可信的,公钥就是可信的。
14. HTTPS 是如何建立连接的?其间交互了什么?
SSL/TLS 协议基本流程:
- 客户端向服务器索要并验证服务器的公钥。
- 双方协商生产【会话密钥】(对称加密密钥)
- 双方采用【会话密钥】进行加密通信。
前两步是 SSL/TLS(SSL和TLS实际上是一个东西,很多文章都把这两者并列称呼) 的建立过程,也就是 TLS 握手阶段,涉及四次通信,使用不同的密钥交换算法,常用的密钥交换算法有两种:RSA 算法和ECDHE 算法。
TLS协议建立的详细流程是:
- ClientHello
首先,由客户端向服务器发起加密通信请求,也就是ClientHello
请求。
在这一步,客户端主要向服务器发送以下信息:
(1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。
(2)客户端生产的随机数(Client Random
),后面用于生成【会话密钥】条件之一。
(3)客户端支持的密码套件列表,如 RSA 加密算法。
- ServerHello
服务器收到客户端请求后,向客户端发出响应,也就是ServerHello
。服务器回应的内容有如下内容:
(1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。
(2)服务器生产的随机数(Server Random
),也是后面用于生产【会话密钥】条件之一。
(3)确认的密码套件列表,如 RSA 加密算法。
(4)服务器的数字证书。
- 客户端回应
客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。
如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:
(1)一个随机数(pre-master key
)。该随机数会被服务器公钥加密。
(2)加密通信算法改变通知,表示随后的信息都将会用【会话密钥】加密通信。
(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务器校验。
客户端和服务器有了三个随机数(Client Random,Server Random,pre-master key),接着就用双方协商的加密算法,各自生成本次通信的【会话密钥】。
- 服务器的最后回应
服务器收到客户端的第三个随机数(pre-master key
)之后,通过协商的加密算法,计算出本次通信的【会话密钥】。
然后,向客户端发送最后的信息:
(1)加密通信算法改变通知,表示随后的信息都将用【会话密钥】加密通信。
(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
至此,整个 TLS 的握手阶段全部结束,接下来客户端和服务器进入加密通信,就完全使用普通的 HTTP 协议,只不过用【会话密钥】加密内容。
基于 RSA 算法的 HTTPS 存在 【前向安全】的问题,如果服务器的私钥泄露了,过去被第三方截获的所有 TLS 通讯密文都会被破解,为了解决这个问题,后面出现了 ECDHE 密钥协商算法,现在大多数网站使用的是这个算法。
15. HTTPS 的应用数据是如何保证完整性的?
TLS 在是线上分为握手协议和记录协议两层:
- TLS 握手协议就是前面的 TLS 四次握手的过程,负责协商加密算法和生成对称密钥,后续用此密钥来保护应用程序数据(即 HTTP 数据);
- TLS 记录协议负责保护应用程序数据并验证其完整性和来源,所以对 HTTP 数据加密是使用记录协议;
以下说的是记录协议的部分,记录协议和握手协议都通过哈希算法保证了完整性
TLS 记录协议主要负责消息(HTTP 数据)的压缩,加密及数据的认证,具体过程为:
- 首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩。
- 接下来,经过压缩的片段会被加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。
- 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密。
- 最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。
记录协议完成后,最终的报文数据将传递到传输控制协议(TCP)层进行传输。
16. HTTPS 一定安全可靠吗?
有一个场景,客户端通过浏览器向服务端发起 HTTPS 请求时,被【假基站】转发到了一个【中间人服务器】,于是客户端和【中间人服务器】完成 TLS 握手,【中间人服务器】再与真正的服务端完成 TLS 握手。
HTTPS 协议本身到目前为止没有任何漏洞,即使成功进行中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书),并不是 HTTPS 不够安全。
为什么抓包工具能截取 HTTPS 数据?
很多抓包工具的工作原理与中间人一致,进行抓包时,需要在客户端安装 Fiddler 的根证书,这里实际上起认证中心(CA)的作用。抓包工具能够抓包的关键是客户端会往系统受信任的根证书列表中导入抓包工具生成的证书,而这个证书会被浏览器信任。
如何避免被中间人抓取数据?
保证电脑安全,不点击任何证书非法的网站。
还可以通过HTTPS 双向认证来避免这种问题,一般 HTTPS 是单向认证,客户端验证了服务端身份,但服务端并不会验证客户端的身份。如果采用双向认证,就解决了被抓取数据的问题。
17. HTTP/1.1 相比 HTTP/1.0 提高了什么性能?
- 使用长连接改善了短连接造成的性能开销。
- 支持管道网络传输,减少整体的响应时间。
性能瓶颈:
- 请求/响应头部未经压缩就发送,首部信息越多延迟越大,只能压缩
Body
的部分。 - 发送冗长的首部。每次互相发送相同的首部造成的浪费多。
- 服务器按请求顺序响应,如果服务器响应慢,会导致队头阻塞。
- 没有请求优先级控制。
- 请求只能从客户端开始,服务器只能被动响应。
18. HTTP/2 做了什么优化?
HTTP/2 基于 HTTPS,所以安全性有保障。
性能改进:
- 头部压缩:HTTP/2会压缩头,如果同时发出多个请求,头是一样的或是相似的,协议会帮助消除重复的部分。这就是所谓的
HPACK
算法,在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,提高速度。 - 二进制格式:HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,而且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。增加了数据传输的效率。
- 并发传输:HTTP/2 引入了 Stream 概念,多个 Stream 复用在一条 TCP 连接,针对不同的 HTTP 请求用独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream,也就是 HTTP/2 可以并行交错地发送请求和响应。
- 服务器推送:HTTP/2 还在一定程度上改善了传统的【请求-应答】工作模式,服务端不再是被动地响应,可以主动向客户端发送消息。客户端和服务器双方都可以建立 Stream,客户端建立的 Stream 必须是奇数号,服务器建立的 Stream 必须是偶数号。
HTTP/2 有什么缺陷
HTTP/2 还是存在”队头阻塞“的问题,因为仍是基于 TCP 协议来传输数据的,TCP 是字节流协议,必须保证收到的字节数据是完整且连续的,当【前1个字节数据】没有到达时,后收到的字节数据只能放在内核缓冲区里
所以,一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有 HTTP 请求都必须等待这个丢了的包被重传回来。
也就是说,HTTP/2的多路复用和流特性解决了多个请求和响应在同一个TCP连接上的队头阻塞,但是不能解决TCP层的队头阻塞问题,丢包仍然能影响到整个TCP连接上的所有流,尽管有一些机制减轻这种影响。
19. HTTP/3 做了哪些优化?
HTTP/1.1 中的管道虽然解决了请求的队头阻塞,但是没有解决响应的队头阻塞,这属于 HTTP 层队头阻塞,HTTP/2 虽然通过多路复用一个 TCP 连接解决了 HTTP 层的队头阻塞,但是一旦发生丢包,就会阻塞住所有的 HTTP 请求,这属于 TCP 层队头阻塞。
所以,HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP。
UDP 发送不管顺序,不管丢包,所以不会出现队头阻塞,UDP 是不可靠传输,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。
QUIC 有以下三个特点:
- 无队头阻塞:有类似 HTTP/2 Stream 与多路复用的概念,QUIC 有自己的一套机制可以保证传输的可靠性。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题 ,所以,QUIC 连接上的多个 Stream 之间是独立的。
- 更快的连接建立:对于 HTTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层、openssl 库实现的表示层,因此它们难以合并在一起,需要分批次握手,先 TCP 握手,再 TLS 握手。
HTTP/3 在传输数据前虽然需要 QUIC 协议握手,然而这个握手过程只需要== 1 RTT(Round-Trip Time,往返时延,网络性能的重要指标,是衡量数据包从发送方发出,到达接收方,然后再从接收方返回发送方所需的总时间),握手的目的是确认双方的【连接 ID】,连接迁移就是基于连接 ID 实现的。因为 HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是 QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的 ”记录“。再加上 QUIC 使用的是 TLS/1.3,仅需 1 RTT 可以同时完成建立连接和密钥协商。
总之,按 TLS 1.2 来说,HTTP/1 和 HTTP/2 的 TCP+TLS 是 3 RTT,因为 TCP 三次握手是 1 RTT,TLS 四次握手是 2 RTT,而 TLS 1.3 优化了过程使得 TLS 三次握手 1 RTT,TCP+TLS 是 2 RTT,而 QUIC 是 1 RTT,再次连接分别都减少了 1 RTT,这使得 QUIC 可以做到 0 RTT 的效果。
- 连接迁移:基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接,给用户的感觉就是网络突然卡顿了一下。
而 QUIC 协议没有用四元组的方式来绑定连接,而是通过连接 ID来标记通信的两个端点,因此即使网络变化后 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以无缝复用原连接。
所以,QUIC 是一个在 UDP 之上的 伪 TCP + TLS + HTTP/2的多路复用的协议。由于 QUIC 是新协议,所以很多网络设备只会当作 UDP,有的网络设备是会丢掉 UDP 包的,HTTP/3 的普及进度非常缓慢。