TCP的SACK(选择性确认)选项格式与传输中的交互流程详解
字数 1905 2025-12-09 18:51:04
TCP的SACK(选择性确认)选项格式与传输中的交互流程详解
描述
TCP的SACK(Selective Acknowledgment,选择性确认)是一种在TCP连接中优化重传的机制。传统TCP使用累积确认(Cumulative ACK),只能确认连续接收的数据,若发生非连续数据段丢失,发送方需重传所有未被确认的数据(即使部分数据已正确接收)。SACK允许接收方通过SACK选项,在ACK报文中告知发送方已接收的非连续数据块,从而让发送方仅重传缺失的数据段,提高传输效率。
1. SACK选项格式
SACK选项是TCP头部可选字段之一,格式如下:
- 类型(Kind):1字节,固定为
5,表示这是一个SACK选项。 - 长度(Length):1字节,指示SACK选项的总字节数(包括Kind和Length字段)。每个SACK块占8字节,长度值 = 2 + 8 × SACK块数。
- SACK块列表:每个SACK块包含两个32位边界:
- 左边界:已接收数据块的起始序列号(不含该序号,即第一个未接收的序列号)。
- 右边界:已接收数据块的结束序列号(含该序号减一,即最后一个已接收的序列号+1)。
注意:SACK块描述的是已接收的数据范围,且通常与ACK字段的累积确认序列号结合使用。
示例:
若ACK=5001,SACK块=[5001, 6001),表示序列号5000之前的数据已确认,且序列号5000-6000(不含6000)的数据块已接收但非连续。
2. SACK协商与启用
SACK在TCP三次握手阶段通过选项协商:
- 双方在SYN或SYN-ACK报文中携带
SACK-permitted选项(Kind=4,Length=2),表示支持SACK。 - 只有双方都声明支持SACK,后续数据传输中才能使用SACK选项。
3. 数据传输中的SACK交互流程
假设发送方发送序列号1001-2000、2001-3000、3001-4000三个数据段,并发生非连续丢失:
步骤1:正常发送与部分接收
- 接收方正确收到1001-2000和3001-4000,但2001-3000丢失。
- 接收方发送ACK=2001(累积确认,期望下一个序列号),并携带SACK选项:
SACK块=[3001, 4001)。
含义:确认了1001-2000的数据,并告知发送方“3001-4000已收到,但2001-3000缺失”。
步骤2:发送方处理SACK信息
- 发送方维护“SACK接收数据图”,记录已被SACK确认的非连续数据块。
- 根据ACK=2001,发送方知道2001之前的数据已确认,但2001-3000未确认。
- SACK块[3001,4001)表明3001-4000已接收,因此发送方仅需重传2001-3000。
步骤3:重传与后续确认
- 发送方重传2001-3000后,接收方收到该段,数据变为连续(1001-4000)。
- 接收方发送ACK=4001(累积确认),无需携带SACK选项。
4. 多个SACK块的处理
若接收方有多个非连续数据块,可在同一ACK中携带最多4个SACK块(受TCP选项长度限制,通常最多4块)。
示例:
- 接收数据:1001-2000、3001-4000、5001-6000(缺失2001-3000、4001-5000)。
- ACK=2001,SACK块=[3001,4001)、[5001,6001)。
- 发送方重传2001-3000后,接收方ACK=4001,SACK块=[5001,6001)(剩余一个非连续块)。
5. SACK与重传超时(RTO)的协同
- 当发生丢包时,SACK可触发快速重传(基于重复ACK),无需等待超时。
- 发送方根据SACK信息更新“重传队列”,仅重传未被SACK覆盖的缺失数据段。
- 若网络拥塞严重,SACK可能多次重复同一数据块信息,发送方需结合拥塞控制算法(如NewReno或CUBIC)调整拥塞窗口。
6. SACK的局限性
- 资源开销:发送方需维护SACK数据图,增加内存与计算负担。
- ACK丢失:若携带SACK的ACK丢失,发送方可能无法及时更新接收状态,但可通过后续SACK恢复。
- 与旧协议兼容:仅当两端支持SACK时生效,否则回退到累积确认。
总结
SACK通过允许接收方“选择性确认”非连续数据,显著减少了不必要的重传,尤其在多个数据段丢失时提升性能。其核心在于SACK选项格式的设计、握手阶段的协商,以及发送方对SACK信息的实时处理。结合快速重传与拥塞控制,SACK成为现代TCP实现高可靠传输的关键机制之一。