目录
QUIC相关文章见《QUIC的那些事 | QUIC概述》《QUIC的那些事 | 包类型及格式》
QUIC的帧包是基于帧的。帧有1个字节的帧类型字段,类型字段后是与类型相关的帧头信息。所有的帧都被包含在单个的QUIC包中,没有帧可以跨越QUIC包的边界。
Frame Type
帧分为普通帧和特殊帧两种类型,普通帧只使用帧类型字节,而特殊帧既使用帧类型字段及帧类型字段中的相关位。
普通帧类型如图 1所示:

特殊帧类型如图2所示:

Stream Frame
Stream帧既用于隐式的创建stream,也在stream上传输数据。其格式如图3所示:

Frame Type字段含义如下:
Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
Bit7:最左边一位,必须设置为1,表明是Stream帧
Bit6:如果被置为1,表明发送端在这个stream上已经结束发送数据,希望处于半关闭状态
Bit5:表示Stream头中是否有Data length字段,设置为0表示无DataLength字段
Bit4,3,2:表示Offset字段的长度:0, 16, 24, 32, 40, 48, 56, or 64位。对应关系如下:
Offset长度 | Bit4,3,2取值 |
64 | 111 |
56 | 110 |
48 | 101 |
40 | 100 |
32 | 011 |
24 | 010 |
16 | 001 |
0 | 000 |
Bit1,0:表示StreamID字段的长度:8,16,24,32位,对应关系如下:
StreamID长度 | Bit1,0取值 |
32 | 11 |
24 | 10 |
16 | 01 |
8 | 00 |
StreamID:长度可变的用于标识stream唯一的无符号值。
Offset:长度可变的用于标识本次数据块在整个stream中偏移字节的无符号值。
Data Length:一个可选的16位的无符号数,用于标识本stream帧中的数据长度。当数据包是”Full-sized”时,可以不填。
Stream帧必须要么包含长度不为0的数据或者FIN位被置为1.
ACK Frame
ACK帧用于告知对端哪些包已经被收到,哪些包被接收端依然认为丢失。QUIC的ACK帧的设计和TCP、SCTP的SACK机制不同:QUIC的ACK表示迄今为止观察到的最大Packet Number,随后是丢失数据包列表,或者NACK,范围表示在此Packet Number之下接收到的数据包的间隔。格式如图 4所示:

Type字段含义如下:
Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
Bit7,6:必须设置为01,标识是ACK报文
Bit5:标识是否含有NACK范围
Bit4:标识ACK帧是否被截断。截断场景:完整的AK报文太长,或者NACK的数量太多超出了可报告的范围(一次最多报告255个)。
Bit3,2:标识Largest Observed字段的长度:1,2,4,6字节,映射关系为:
StreamID长度 | Bit3,2取值 |
6 | 11 |
4 | 10 |
2 | 01 |
1 | 00 |
Bit1,0:标识Missing Packet Sequence Number Delta的长度:1,2,4,6字节,映射关系为:
StreamID长度 | Bit1,0取值 |
6 | 11 |
4 | 10 |
2 | 01 |
1 | 00 |
Received Entropy:一个8位无符号值,标识到观察到的最大Packet Number为止的所有接收到的数据包中熵的累积散列值
Largest Observed:长度可变的无符号数,标识已观察到的最大Packet Number
Ack Delay Time:一个16位无符号浮点,有11位标识显式mantissa和5个显式指数位。取值等于发生报文时间到受到请求时间的插值。
Timestamp Section:时间戳相关信息
Missing Packet Section:丢包的相关信息
Revived Packet Section:已接收包的相关信息
STOP_WAITING Frame
STOP_WAITING Frame用于告知对方停止等待packet number小于特定值的相关包,格式如图 5所示

Type:必须设置为0x06,标识是STOP_WAITING Frame。
Least Unacked Delt:长度和包头的packetNumber长度相同。从报头的包号中减去它,以确定未应答的最小值。计算获得的最小未确认数是发送方仍在等待ACK的所有数据包中的最小packet number。如果接收端丢失了任何小于此值的数据包,则接收端应将这些数据包视为无法恢复的丢失。.
WINDOW_UPDATE Frame
WINDOW_UPDATE Frame用于告知对端增加flow control window大小,格式如图 6所示

Type:必须设置为0x04
Stream ID:需要对flow control window进行控制的stream的ID,为0时用于确定连接层面的flow control window
Byte Offset:可以在StreamID上进行传输的报文的绝对字节偏移。对于连接层面的flow control ,该值标识可以在所有当前打开的stream上发送的字节
BLOCKED Frame
BLOCKED Frame用于告知对方,本方已经准备好发送数据(并且有数据要发送),但是因为当前的流控被阻塞了。格式如图 7

Type:必须设置为0x05
Stream ID:标识哪个stream被阻塞了,为0标识在连接被阻塞。
Padding Frame
Padding帧只包含Frame Type字段,且必须设置为0x00,当出现该帧时,这个报文后续的部分就是填充字节。
RST_STREAM Frame
功能同TCP的RST,用于标识stream的异常终止。如果由stream的创建者发送,标识创建者准备取消这个stream;如果是由该stream的接收者发送,表示出现了问题或者接收者不准备接收stream,格式如图 8所示:

Type:必须设置为0x01
Stream ID:准备终止的Stream
Byte offset:64位的无符号整数,标识这个stream的终止数据的绝对偏移
ErrorCode:stream关闭的原因
PING Frame
类似于ping操作,用于确定对端是否还在线。只有帧类型字段(1字节),必须设置为0x07。默认是15s发送一次,比大多数NAT的时间要短,保证连接不被NAT断开。
CONNECTION_CLOSE帧
CONNECTION_CLOSE帧用于标识连接即将被关闭。如果有stream处于在途状态,当连接被关闭时,这些stream也会被关闭。

Type:必须设置为0x02
ErrorCode:关闭连接的原因
Reason phrase:可读的用于解释连接关闭的原因
GOAWAY Frame
GOAWAY 帧用于通知连接应该停止使用,以后连接会终止。活跃的stream会被继续处理,但是发送Goaway帧的发送者不在初始化其他任何stream,并且也不接受新stream.

Type:必须设置为0x06
ErrorCode:关闭连接的原因
Last Good Stream ID:GOAWAY消息的发送者接受的最后一个流ID。如果没有流被回复,则必须将此值设置为0。
Reason phrase:可读的用于解释连接关闭的原因
参考资料
https://tools.ietf.org/html/draft-tsvwg-quic-protocol-02#ref-3
