quic协议go语言 quit协议( 三 )


QUIC 的流量控制 [22] 类似 HTTP2,即在 Connection 和 Stream 级别提供了两种流量控制 。为什么需要两类流量控制呢?主要是因为 QUIC 支持多路复用 。
Stream 可以认为就是一条 HTTP 请求 。
Connection 可以类比一条 TCP 连接 。多路复用意味着在一条 Connetion 上会同时存在多条 Stream 。既需要对单个 Stream 进行控制 , 又需要针对所有 Stream 进行总体控制 。
QUIC 实现流量控制的原理比较简单:
通过 window_update 帧告诉对端自己可以接收的字节数,这样发送方就不会发送超过这个数量的数据 。
通过 BlockFrame 告诉对端由于流量控制被阻塞了,无法发送数据 。
QUIC 的流量控制和 TCP 有点区别,TCP 为了保证可靠性,窗口左边沿向右滑动时的长度取决于已经确认的字节数 。如果中间出现丢包,就算接收到了更大序号的 Segment,窗口也无法超过这个序列号 。
但 QUIC 不同,就算此前有些 packet 没有接收到,它的滑动只取决于接收到的最大偏移字节数 。
QUIC 的多路复用和 HTTP2 类似 。在一条 QUIC 连接上可以并发发送多个 HTTP 请求 (stream) 。但是 QUIC 的多路复用相比 HTTP2 有一个很大的优势 。
QUIC 一个连接上的多个 stream 之间没有依赖 。这样假如 stream2 丢了一个 udp packet,也只会影响 stream2 的处理 。不会影响 stream2 之前及之后的 stream 的处理 。
这也就在很大程度上缓解甚至消除了队头阻塞的影响 。
quic 协议总结client和server协商过程:
1. 客户端发送CHLO到服务端
2. 服务端回送的REJ信息给客户端,同时携带上原地址标识信息和服务端证书信息
3. 客户端再次发送CHLO到服务端
拥塞控制:
QUIC参考TCP的CUBIC拥塞控制算法,并在试探尝试其他拥塞控制算法
试探尝试新的拥塞控制算法:例如每个数据包的转发(包括原始数据包和重传包)都携带一个新的sequece序列化,这样可以避免TCP的重传模糊问题
QUIC-ACK会携带上接收数据包的时间以及发送ack的时间,这样有利于计算往返时延
QUIC-ACK相比TCP的SACK , 跟容易实现包的重组,当有包丢失或者
FEC
通过FEC可以从一组FEC报文组中恢复网络传输中丢失的数据包,具体优化方案由发送端决定
连接复用
QUIC连接通过一个64位的连接标识符标识,该标识符由客户端产生 。
QUIC的连接建立将版本协商与加密和传输握手交织在一起以减少连接建立延迟 。我们将在下面首先描述版本协商 。
连接建立延迟
灵活的拥塞控制
多路复用而不存在队首阻塞
认证和加密的首部和载荷
流和连接的流量控制
连接迁移
QUIC采用了两级密钥机制:初始密钥和会话密钥 。初次连接时不加密 , 并协商初始密钥 。初始密钥协商完毕后会
马上再协商会话密钥,这样可以保证密钥的前向安全性,之后可以在通信的过程中就实现对密钥的更新 。接收方意
识到有新的密钥要更新时,会尝试用新旧两种密钥对数据进行解密,直到成功才会正式更新密钥,否则会一直保留
旧密钥有效 。
QUIC在握手过程中使用Diffie-Hellman算法协商初始密钥,初始密钥依赖于服务器存储的一组配置参数 , 该参数
会周期性的更新 。初始密钥协商成功后,服务器会提供一个临时随机数,双方根据这个数再生成会话密钥 。
0-RTT握手过程
QUIC握手的过程是需要一次数据交互 , 0-RTT时延即可完成握手过程中的密钥协商 , 比TLS相比效率提高了5倍,且具有更高的安全性 。

推荐阅读