TCP 中的选择性确认 (SACK)
当客户端和服务器之间的 TCP 通信中检测到数据包丢失时,下一步是恢复丢失的数据包。 TCP中有一些丢失恢复的算法。这些是:
- 快速恢复
- 选择性确认 (SACK)
- 比例降息 (PRR)
快速恢复的局限性:
TCP Reno 中的“快速恢复”机制有两个主要问题。
- 多次减少同一组数据包的拥塞窗口 (cwnd)。 TCP New Reno 解决了这个问题。
- 从在同一个拥塞窗口中丢失的多个数据包中恢复需要很长时间。选择性确认 (SACK) 解决了这个问题。
选择性确认(SACK):
SACK 是对 TCP 的发送方和接收方优化。发送方和接收方都应该支持 SACK 功能,然后才可以使用它。 SACK 功能在所有操作系统(即 Linux、Windows 和 macOS)中默认启用。 SACK 不会替换 TCP 标头中的原始 ACK,而是在 TCP 标头的选项字段中添加另一个字段用于 SACK 信息。 TCP 标头中的“选项”字段用于发送 SACK,而不是调整实际的 ACK 字段。 “选项”字段中的 SACK 最多可使用 32 个字节(共 40 个字节)。 “选项”字段中的 8 个字节已为“时间戳”保留。
SACK的工作:
SACK 功能可帮助发送方识别接收方缓冲区中的“间隙”。当接收器没有按顺序接收数据包时,缓冲区中存在一些漏洞(缺失点)。 SACK 帮助发送者及早了解接收缓冲区中的这些漏洞。当发送者知道漏洞或丢失的数据包时,它会同时重新传输它们。与快速恢复不同,SACK 不会很晚才通知发送者丢失的数据包。
解释:
发送方最初同时发送数据包 0、1、2、3和 4 。接收方接收到 packet-0 并通过发送 ACK-1 请求下一个排序的数据包。
发送方得到 ACK-1 并发送 packet-5 以保持 cwnd=5。
由于网络拥塞,数据包 1 被丢弃。
接收方获得数据包 2。发送 packet-6 以保持 cwnd=5。现在接收器正在乱序获取数据包。它通过发送 ACK-1 请求数据包 1,并为下一个所需数据包创建 SACK 块。确认字段将继续发送重复号码。接收方发送 ACK-1 和 SACK 2-3。 ACK-1 表示接收方正在请求 packet-1。 SACK 2-3 表示接收方收到了数据包 2 并请求数据包 3。
Packet=3 被丢弃。
接收方获得数据包 4。发送 packet-7 以保持 cwnd=5。接收缓冲区看起来像:[0, 2, 4]。所以,它的缓冲区有两个洞。接收方发送 ACK-1 和 SACK 2-3、4-5。表示接收方已收到数据包 2 和 4 并要求数据包 3 和 5。还发送第二个重复的 ACK-1。
接收方得到数据包=5。接收方发送 ACK-1 和 SACK 2-3、4-6。
发送方获得第三次重复的 ACK-1,因此它进入快速恢复阶段,同时发送所有丢失的数据包到现在。接收方正在请求数据包 1 和 3。
分组 1 的丢失由 ACK 字段传达,分组 3 的丢失由 SACK 传达。
发送方重新传输数据包 1 和 3。Inflight 看起来像 6、7、1、3
接收方成功接收到 packet-6。
当接收者收到 packet-1 时。缓冲区看起来像:[0, 1, 2, 4, 5, 6]。缓冲区还有一个洞。
接收方发送 ACK-3、SACK 4-7。 ACK-3 表示接收方已按顺序接收到 packet-2。 SACK 4-7 表示接收方收到了数据包 4、5 和 6,并请求 7。
当接收方收到数据包 3 时。缓冲区看起来像:[0, 1, 2, 3, 4, 5, 6]。现在所有的数据包都按顺序到达了。接收方发送 ACK-7 请求下一个数据包。
接收方成功接收到数据包 7 并请求下一个数据包 8。
TCP 标头中的 SACK:
SACK 扩展使用“两个”TCP 选项。 ' SACK-Permitted ' 选项与 SYN 数据包一起使用。当客户端第一次与服务器对话时,它会告诉服务器使用 SACK。第二个选项是“ SACK ”选项,它仅在接收方获取数据包乱序时使用。第一个选项是让服务器知道客户端支持 SACK,作为响应,服务器客户端将知道服务器是否支持 SACK。
“允许 SACK”选项:
Kind=4, Length=2
“SACK 选项”:
Kind=5, Length=8*number of SACK blocks.
“SACK 块”:
|Left edge of block of size 4 bytes||| Right edge of block of size 4 bytes|
每个 SACK 块需要 8 个字节。 4 个字节用于块的左边缘。块的右边缘为 4 个字节。边 = 32 位(4 字节)长的序列号。
SACK 限制:
一个段中接收器最多可以报告四个 SACK 块。一个 SACK 块需要 8 个字节,因此 8 x 4 个 SACK 块 = 32 个字节可用于 SACK 块。因为为 TCP 时间戳选项保留了 8 个字节(种类 = 8,长度 = 10)。
8 字节的 TCP 时间戳 + 32 字节的 SACK = 40 字节(TCP 选项字段的总容量)。
SACK 的增强功能
- 前向确认 (FACK)
- 重复选择性确认 (DSACK)
- 最近的确认 (RACK)
为什么 SACK 对无线网络有好处?
SACK 对无线网络有好处,因为无线网络报告多个数据包丢失的速度更快。数据包丢失和重传在无线环境中更为频繁。接收方的应用程序不需要等待更长的时间来填充接收缓冲区中的“间隙”。
SACK 最小化流完成时间 (FCT)。可以在单个 SACK 块中报告连续的数据包丢失。 SACK 在很大程度上提高了性能,因为所有的数据包都是立即重传的。发送者可以准确地测量飞行中的数据包数量。它提供了对“交付率”的更好估计。它对于像 Westwood 这样依赖于估计 TCP 连接的“数据速率”的算法很有用。