当前位置:   article > 正文

QUIC协议连接原理和特性

QUIC协议连接原理和特性

概述

QUIC全称 Quick UDP Internet Connection(快速UDP互联网连接),是由Google提出的使用UDP协议进行多路并发传输的协议。目的是保证可靠性的同时降低网络延迟。

QUIC相比现在广泛应用的HTTP/2.x + TCP + TLS协议主要有这些优势:减少了TCP三次握手及TLS握手时间、改进的拥塞控制、避免HOL(队头阻塞)的多路复用、连接迁移、前向冗余纠错。

 

实现原理

先分析HTTPS的握手过程(包括TCP握手和TLS握手)

以一次简单的浏览器访问为例:

1、DNS域名解析获得ip,需要1RTT

2、TCP握手 三次握手需要1RTT

3、TLS握手 需要 2RTT

 

https总共耗时3RTT

而QUIC首次建立连接只需1RTT,再次连接只需0RTT

 

握手流程示例

在QUIC中,数据包编号分为3个空间:

初始(Initial)、握手(Handshake)、应用数据(Application data)

//1-RTT
Client                                                  Server
​
Initial[0]: CRYPTO[CH] ->
​
                                 Initial[0]: CRYPTO[SH] ACK[0]
                       Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
                                 <- 1-RTT[0]: STREAM[1, "..."]
​
Initial[1]: ACK[0]
Handshake[0]: CRYPTO[FIN], ACK[0]
1-RTT[0]: STREAM[0, "..."], ACK[0] ->
​
                                          Handshake[1]: ACK[0]
         <- 1-RTT[1]: HANDSHAKE_DONE, STREAM[3, "..."], ACK[0]

客户端第一个报文是 Initial 类型,包编号为 0,并且包含一个携带 ClientHello(缩写:CH) 的 CRYPTO 帧。

 

服务端回包:

 

//0-RTT
Client                                                  Server
​
Initial[0]: CRYPTO[CH]
0-RTT[0]: STREAM[0, "..."] ->
​
                                 Initial[0]: CRYPTO[SH] ACK[0]
                                  Handshake[0] CRYPTO[EE, FIN]
                          <- 1-RTT[0]: STREAM[1, "..."] ACK[0]
​
Initial[1]: ACK[0]
Handshake[0]: CRYPTO[FIN], ACK[0]
1-RTT[1]: STREAM[0, "..."] ACK[0] ->
​
                                          Handshake[1]: ACK[0]
         <- 1-RTT[1]: HANDSHAKE_DONE, STREAM[3, "..."], ACK[1]

连接迁移

基于UDP的QUIC连接迁移实现

tcp连接是由(源IP,源端口,目的IP,目的端口)四个信息共同标识。比如手机在wifi和4g移动网络中切换时客户端ip肯定会发生变化,需要重新建立和客户端的tcp连接。

而QUIC基于连接ID唯一识别连接,当源地址发生改变时,QUIC仍然可以保证连接存活和数据正常收发。

那 QUIC 是如何做到连接迁移呢?很简单,QUIC是基于UDP协议的,任何一条 QUIC 连接不再以 IP 及端口四元组标识,而是以一个 64 位的随机数作为 ID 来标识,这样就算 IP 或者端口发生变化时,只要 ID 不变,这条连接依然维持着,协议层只需要将控制块中记录的Source Ip 和Port信息更新即可,不需要像TCP那样先断开连接,就可以保证连接顺畅迁移或切换,用户基本不会感知到切换过程

由于这个 ID 是客户端随机产生的,并且长度有 64 位,所以冲突概率非常低。

 

用wireshark对QUIC协议进行抓包,可以看到捕获到的Connection ID与终端使用的连接ID相同

无队头阻塞

TCP 采用滑动窗口机制来提高数据传输效率。窗口大小就是指无需等待确认应答而可以继续发送数据的最大值,这个机制实现了使用大量的缓冲区,通过对多个数据包同时进行确认应答的功能。当可发送数据的窗口消耗殆尽时,就需要等待收到连续的确认应答后,当前窗口才会向前滑动,为发送下一批数据包腾出窗口。假设某个数据包超时未收到确认应答,当前窗口就会阻塞在原地,重新发送该数据包,在收到该重发数据包的确认应答前,就不会有新增的可发送数据包了。也就是说,因为某个数据包丢失,当前窗口阻塞在原地,同样阻塞了后续所有数据包的发送。(TCP 队头阻塞的主要原因是数据包超时确认或丢失阻塞了当前窗口向右滑动)

QUIC 使用的Packet Number 单调递增的设计,可以让数据包不再像TCP 那样必须有序确认,QUIC 支持乱序确认,当数据包Packet N 丢失后,只要有新的已接收数据包确认,当前窗口就会继续向右滑动

既然重传数据包的Packet N+M 与丢失数据包的Packet N 编号并不一致,我们怎么确定这两个数据包的内容一样呢?有了Stream Offset 字段信息,属于同一个Stream ID 的数据包也可以乱序传输了

 

上图中数据包Packet N 丢失了,后面重传该数据包的编号为Packet N+2,丢失的数据包和重传的数据包Stream ID 与 Offset 都一致,说明这两个数据包的内容一致。这些数据包传输到接收端后,接收端能根据Stream ID 与 Offset 字段信息正确组装成完整的资源。

QUIC 通过单向递增的Packet Number,配合Stream ID 与 Offset 字段信息,可以支持非连续确认应答Ack而不影响数据包的正确组装,摆脱了TCP 必须按顺序确认应答Ack 的限制(也即不能出现非连续的空位),解决了TCP 因某个数据包重传而阻塞后续所有待发送数据包的问题(也即队头阻塞问题)。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/626372
推荐阅读
相关标签
  

闽ICP备14008679号