📖 TCP 的选择确认 (SACK)
🎯 课程摘要:TCP 选择确认 SACK (Selective ACKnowledgment) 用于解决累积确认机制下未按序到达数据被重复重传的问题。接收方通过 SACK 选项告知发送方已收到的不连续字节块边界,使发送方可以只重传缺少的数据。SACK 选项在 TCP 扩展首部的选项字段中实现,最大 40 字节选项字段最多可携带 4 个字节块信息。
📝 详细笔记
1. SACK 的作用与动机
- 问题背景:在 TCP 的快重传和可靠传输中,接收方只能对按序收到的数据中的最高序号给出确认(累积确认)。当发送方超时重传时,接收方之前已收到的未按序到达的数据也会被重传,造成重复传输。
- 概念定义:选择确认 SACK (Selective ACKnowledgment) 使接收方能够准确告知发送方哪些数据已收到、哪些缺失,从而只传送缺少的数据,不重传已正确到达但未按序到达的数据。
- ⚠️ 重点/考点:SACK 的核心价值在于避免对已收到的失序数据的无谓重传,提高网络资源利用率。
2. SACK 的工作原理
- 举例说明:假设接收方收到序号不连续的字节流:
- 序号 1~1000:连续(已收到)
- 序号 1001~1500:缺失
- 序号 1501~3000:连续(已收到,称为第一个字节块)
- 序号 3001~3500:缺失
- 序号 3501~4500:连续(已收到,称为第二个字节块)
- 边界描述:使用两个指针分别指向每个字节块的左边界和右边界:
- 左边界:字节块第一个字节的序号;
- 右边界:字节块后面第一个字节的序号。
- 第一个字节块:左边界=1501,右边界=3001
- 第二个字节块:左边界=3501,右边界=4501
- ⚠️ 重点/考点:接收方将这些字节块边界信息通过 SACK 选项准确告知发送方,使发送方不再重复发送这些数据。
3. SACK 选项格式
- 实现位置:TCP 报文段固定首部中并未为不连续字节块边界信息提供专用字段;RFC 2018 规定在扩展首部的选项字段中实现 SACK 功能。
- 选项字段结构:
内容 字节数 说明 SACK 选项类型 1 指明是否使用 SACK 选项 选项长度 1 指明该选项占用多少字节 字节块边界 每边界 4 字节 TCP 对每字节数据采用 4 字节序号 - 容量计算:
- 一个字节块需要两个边界(左、右)= 2 × 4 = 8 字节;
- 加上 2 字节(类型 + 长度)开销,一个字节块共占 10 字节;
- 选项字段最大长度 40 字节,因此最多只能包含 4 个字节块的信息。
- ⚠️ 重点/考点:边界需 4 字节是因为 TCP 对每个字节采用 4 字节序号;40 字节选项字段上限决定最多 4 个字节块。
4. SACK 的局限
- 发送方响应未标准化:TCP 选择确认的相关文档并没有指明发送方应当怎样响应 SACK 报文段。
- 实际实现:大多数 TCP 实现还是重传所有未被确认的数据块,而非仅重传缺失部分。
- ⚠️ 重点/考点:SACK 主要是接收方向发送方提供更精确的接收状态信息,但发送方如何利用这些信息并无统一标准。
💡 核心总结
- SACK 解决累积确认下失序数据被重复重传的问题,只传缺失数据。
- 接收方用左、右边界指针描述已收到的字节块,通过选项字段告知发送方。
- SACK 在扩展首部选项字段实现:1 字节类型 + 1 字节长度 + 每边界 4 字节。
- 一个字节块需 8 字节(两边界),40 字节选项字段最多容纳 4 个字节块。
- 发送方如何响应 SACK 无标准规定,多数实现仍重传所有未确认数据块。
❓ 课后思考 / 经典考题
- 为什么需要 SACK?它解决了累积确认机制的什么缺陷?
- 一个字节块需要多少字节来描述?为什么每个边界需要 4 字节?
- TCP 选项字段最大长度 40 字节,最多能包含几个字节块的 SACK 信息?
- SACK 选项在 TCP 报文段的哪个部分实现?固定首部中有专用字段吗?
- 发送方收到 SACK 报文段后应如何响应?实际多数 TCP 实现是如何做的?