“沿用QUIC包号与ACK区间:确认属于某一空间、某次发送,较大包号表示较晚发送。本页采用RFC 9002推荐阈值,讨论握手已确认、路径固定、地址验证已完成的Application空间;所有主…”
形式陈述
一次发送有自己的编号
多流重组已经把“这次发送的是哪个包”与“载荷写入哪条流的哪些字节”分开。本页继续使用连接、方向、包号空间组成的包身份;新增的任务是:接收端如何报告已经处理过的包,发送端怎样解释这份报告。假定包已成功解除保护并通过帧处理,连接没有重启;不讨论密钥计算、截断包号恢复或连接迁移。
QUIC v1有三个包号空间:Initial、Handshake、Application Data。0-RTT和1-RTT属于同一个Application空间,1-RTT更新密钥也不另开一份包号。每个发送方向在每个空间从0开始,后续使用的包号严格增大,允许跳过一些号,但不能复用。编号到达协议上限
收到ACK时,承载该ACK的包所属空间决定它确认哪个空间;方向则是对端此前发送的反方向。例如服务器在Handshake包7里确认客户端Handshake包12,不会确认客户端Application包12。ACK自己的承载包号7,也不是被确认包号12。
区间按包号从高到低排列
用闭区间
再按从高到低的顺序携带若干对
其中Gap字段
正向事实不等于整个历史
令本端在某空间实际发送过的包号集合为
集合
直觉
ACK列的是收到的岛,空隙仍需判断
把已处理包号画在数轴上,相邻号码连成一段。ACK把这些“岛”的右端、长度和相邻岛间空隙写出来。Largest是最右侧的一点,不是“所有更小包号都已收到”的承诺。
一个包可以装两条流的帧;确认这个包,说明这次发送携带的帧已经被处理。反过来,同一段流字节可能放在两个不同包里补发。确认其中一个包足以给出该份数据的交付证据,但另一个包仍有自己的包级记录,不能把两个包号合并成一次发送。
例子与边界
六个收到的号怎样写成三个区间
某客户端已发送Application包0至12。服务器成功处理的集合为
| 字段 | 值 | 解码动作 |
|---|---|---|
| Largest | 12 | 第一段最高为12 |
| First Range | 0 | 第一段最低 |
| Range Count | 2 | 还有两组Gap/Range |
| 第一组Gap、Range | 2、1 | 最高 |
| 第二组Gap、Range | 1、2 | 最高 |
第一处空隙是9、10、11,共3个号,所以Gap为2。若错用“下一最高=上一最低−Gap−1”,就会把9误确认为已收到。这个差一错误不仅会多出一个号,还会让发送端误删它的恢复责任。
下一份ACK只有
缺号和错误号各说明什么
包5不在ACK里,可能尚在途中、已经丢失,或不在这次保留的确认范围内。发送者不能仅从一次遗漏就判定网络把它丢掉。包号还允许被主动跳过;例如实际
若Largest为3、First为4,第一段最小值为−1,编码立即非法。若Largest为3、First为0,后续Gap为2,则下一最高为−1,同样非法。检查负数应在删除任何发送记录之前完成。本文检查器还拒绝二元组数量与Range Count不符的输入,避免把截短记录当成一份完整ACK。
丢掉确认历史以后,不能重新接受旧包
有限接收端不可能永久保存每个历史包号。RFC允许缩减ACK范围,但要求一旦丢弃某范围,就确保不会随后再次接受那个范围内的包。一种具体策略是维护单调下界
例如将下界从0推进到7,未来2、3、4连同尚未收到的5、6都将被丢弃;仍记录7、8、12及其间的未收缺口。这里牺牲了低于7的迟到包接纳能力,换取有界历史。流中的尚缺字节仍可在更高的新包号里补发,不能因为释放包号记录就把流缺口当成已填。
推论与应用
确认是恢复控制的输入
QUIC丢包检测会结合已确认的更高包号、发送时刻与RTT估计,对仍未确认的包作阈值判断。ACK提供正向观测,阈值承担推断风险;乱序足够大时,推断也可能错误。
字节流的最终长度仍由流信用与最终大小处理。收到某个FIN所在包的ACK,不会把另一方向也关掉;收到某个普通数据包的ACK,也不说明远端应用已完成一次业务事务。这些分别是发送方向、流状态与应用语义的问题。
处理成本取决于表示和输出
若一帧含
参考资料
[1] Jana Iyengar、Martin Thomson,RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport,2021,§12.3包号空间与重复处理,§13.1成功处理后确认,§13.2.3确认范围管理,§19.3与§19.3.1的字段及递推式。数值集合与报错输入为本页教学实例。