TCP 6(重传机制)

tcp重传机制

TCP 的可靠性,很大程度上依赖于其精妙的重传机制。当数据包在网络中丢失或乱序时,TCP 能够自动发现并重新发送,确保数据最终能够完整、有序地到达目的地。

这套机制主要由两个核心部分组成:超时重传和快速重传。

超时重传 (Timeout Retransmission)

这是 TCP 重传机制的"兜底方案",也是最基础的保障。它的核心思想很简单:发送方为每一个发出的数据包启动一个计时器,如果在规定时间内没有收到接收方的确认(ACK),就认为数据包已经丢失,并重新发送。

核心:动态计算超时时间 (RTO)

超时重传的关键在于如何设置这个"规定时间",即重传超时时间 (RTO, Retransmission Timeout)

  • RTO 太短:会导致不必要的重传,浪费网络带宽,加剧网络拥塞。
  • RTO 太长:在真正丢包时,应用程序会因等待过久而感知到明显的延迟。

因此,TCP 不会使用一个固定的 RTO 值,而是根据网络的实时状况动态计算。它通过测量数据包发出到收到确认的时间,即往返时间 (RTT, Round-Trip Time),来估算 RTO。

为了应对网络抖动,TCP 采用了一套平滑算法来更准确地预测 RTO:

  1. 平滑往返时间 (SRTT):对多次测量的 RTT 样本进行加权平均,得到一个相对稳定的 RTT 值。
  2. 往返时间变化量 (RTTVAR):用来衡量 RTT 的波动程度。网络越不稳定,这个值越大。

最终,RTO 的计算公式(遵循 RFC 6298 标准)为:
RTO = SRTT + 4 * RTTVAR

这个公式确保了 RTO 值通常会比平均 RTT 长,以容纳正常的网络延迟波动,避免误判。

优化:指数退避 (Exponential Backoff)

当发生超时重传后,如果网络依然拥塞,连续的重传可能会加重问题。为此,TCP 采用了指数退避策略:

  • 每次重传后,下一次的 RTO 时间会翻倍(例如,第一次 RTO 是 1 秒,第二次就是 2 秒,第三次是 4 秒)。
  • 这种策略可以有效减轻网络负载,给网络一个"喘息"的机会。如果重传次数超过上限(例如 5 次),TCP 会认为网络出现了严重故障,并关闭连接。

快速重传 (Fast Retransmit)

超时重传虽然可靠,但有时等待时间过长。为了提升效率,TCP 引入了快速重传机制作为优化。它不依赖计时器,而是通过接收方的反馈来立即发现丢包。

触发条件:3 个重复 ACK

快速重传的触发依赖于一个关键信号:收到 3 个重复的 ACK

工作流程如下:

  1. 假设发送方按顺序发送了数据包 P1, P2, P3, P4, P5。
  2. 接收方收到了 P1,回复 ACK=2(期望收到 P2)。
  3. P2 在网络中丢失了
  4. 接收方收到了 P3,发现顺序不对(它还在等 P2),于是它不能确认 P3,只能再次回复 ACK=2,告诉发送方"我还在等 P2"。
  5. 接着,接收方又收到了 P4 和 P5,它们同样会触发回复 ACK=2
  6. 当发送方连续收到 3 个 针对 P2 的重复 ACK(即总共收到 4 个 ACK=2)时,它就不再等待 RTO 计时器超时,而是立即重传丢失的数据包 P2。

这种机制大大缩短了丢包恢复的时间,通常能在大约一个 RTT 内完成重传,而不是等待可能长达数秒的 RTO。

高级优化:选择性确认 (SACK)

SACK(Selective Acknowledgment,选择性确认)选项是TCP协议的一项扩展,旨在解决传统TCP在数据包丢失时重传效率低下的问题。它允许接收方精确地告知发送方哪些数据已经成功接收,即使这些数据不是按顺序到达的,从而避免了不必要的重传。

传统TCP确认机制的局限

为了理解SACK的价值,我们先看一个传统TCP确认机制(累积确认)的例子:

  1. 发送数据 :假设发送方连续发送了数据包 1, 2, 3, 4, 5, 6
  2. 发生丢包 :数据包 3 在网络中丢失,但 1, 2, 4, 5, 6 都成功到达了接收方。
  3. 接收方反馈 :接收方收到了乱序的数据包 4, 5, 6,但由于它只能进行"累积确认",即只能确认到最后一个按序到达的数据,所以它只能向发送方回复 ACK=2,意思是"我已收到2及之前的所有数据,现在期待收到3"。
  4. 发送方行为 :发送方收到 ACK=2 后,会认为从数据包 3 开始的所有后续数据(3, 4, 5, 6)都已丢失,即使 4, 5, 6 已经安全抵达。因此,它会重传 3, 4, 5, 6 这四个数据包。

这个过程造成了带宽的浪费,因为数据包 4, 5, 6 被重复发送了。

SACK选项的工作原理

SACK通过引入"选择性确认"解决了上述问题。它的工作流程分为两个阶段:

1. 能力协商阶段

在TCP连接建立的三次握手阶段,通信双方会协商是否支持SACK功能。

  • 客户端在发送的第一个 SYN 包中,会带上一个 SACK-permitted 的TCP选项。
  • 服务器如果在 SYN-ACK 响应中也带上 SACK-permitted 选项,就表示双方都支持SACK,后续传输中就可以使用该功能。
2. 数据传输阶段

当连接中发生丢包时,SACK机制就会发挥作用:

  1. 发送数据 :同样,发送方发送了数据包 1, 2, 3, 4, 5, 6
  2. 发生丢包 :数据包 3 丢失,1, 2, 4, 5, 6 到达接收方。
  3. 接收方反馈 :接收方在回复 ACK=2(累积确认)的同时,会在TCP报文的选项字段中添加一个 SACK选项 。这个选项会明确指出已经收到的非连续数据块,例如 SACK [4-6],表示"虽然我在等3,但我已经把4到6号数据都收到了,请帮我记下来"。
  4. 发送方行为 :发送方解析SACK选项后,就能精确地知道只有数据包 3 丢失了。因此,它只需要重传数据包 3 ,而不会再浪费资源重传已经成功送达的 4, 5, 6
SACK的优势

通过这种方式,SACK带来了显著的性能提升,尤其是在高丢包率的网络环境(如无线网络)中:

  • 减少冗余重传:只重传真正丢失的数据包,极大地节省了网络带宽。
  • 提升传输效率:避免了因单个丢包导致整个传输窗口停滞,保持了较高的吞吐量。
  • 降低传输延迟:发送方能更快地识别并修复丢包,减少了等待超时重传的时间。

D-SACK

如果说 SACK 是为了"精准重传",那么 D-SACK (Duplicate SACK) 就是为了"精准诊断"。

D-SACK 是 SACK 的一项扩展(定义于 RFC 2883),它的主要作用不是告诉发送方"我缺什么",而是告诉发送方**"我收到了重复的数据"**。这听起来可能像是一个微不足道的细节,但它能让发送方极其聪明地推断出网络到底发生了什么故障,从而避免不必要的性能下降。

在普通的 SACK 机制中,SACK 块告诉发送方哪些数据已收到但未按序到达。而在 D-SACK 中,接收方利用 SACK 选项的第一个块来报告重复接收的数据段。

判定规则(接收方):

接收方通过以下两种方式之一来标记 D-SACK:

  1. 起始序号小于确认号 (ACK Number): 如果第一个 SACK 块的起始序号小于 ACK 字段中的序号,说明这个块包含的数据已经被累积确认过了,是重复的。
  2. 包含在第二个 SACK 块中: 如果第一个 SACK 块的范围完全被第二个 SACK 块覆盖,也说明它是重复的。

工作流程示例:

  1. 发送 :发送方发送数据包 Seq 1000-1499
  2. 丢包/延迟 :接收方没收到 1000-1499,但收到了后续的 1500-19992000-2499。接收方回复 ACK 1000 并带上 SACK 1500-2500
  3. 触发重传 :发送方收到 3 个重复的 ACK 1000,触发快速重传 ,重新发送 Seq 1000-1499
  4. 意外到达 :就在重传的同时,原本那个"迟到"的原始包 Seq 1000-1499 终于到达了接收方。
  5. D-SACK 响应 :接收方此时收到了两份 1000-1499。它会回复 ACK 2500(表示数据已补齐),并在 SACK 选项中放入 D-SACK 1000-1500,明确告诉发送方:"你刚才重传的那个包,我其实早就收到了,这是重复的。"

D-SACK 的核心价值:网络故障诊断

D-SACK 最大的意义在于它赋予了发送方区分网络故障类型的能力。通过收到 D-SACK,发送方可以做出更明智的决策,而不是盲目地降低传输速度。

1. 区分"丢包"与"乱序/延迟"
  • 场景:发送方触发了快速重传。
  • 无 D-SACK :发送方假设包丢了,认为网络拥塞,于是减小拥塞窗口 (cwnd),降低发送速度。
  • 有 D-SACK :发送方意识到包没丢,只是乱序了。它会认为网络并没有拥塞,因此不减小(或撤销减小)拥塞窗口,保持高速传输。
2. 区分"数据包丢失"与"ACK 丢失"
  • 场景:接收方收到了所有数据,但 ACK 应答包在路上丢了。发送方超时重传。
  • D-SACK 反馈:接收方收到重传包后,回复 D-SACK。
  • 结果:发送方得知数据没丢,是 ACK 丢了。这有助于发送方调整重传超时时间 (RTO),避免过于敏感的超时重传。
3. 检测数据包复制
  • 如果网络中存在设备错误地复制了数据包,D-SACK 也能帮助发送方发现这一异常。

SACK 解决了"缺什么补什么"的问题,提升了传输效率;而 D-SACK 解决了"为什么补"的问题,提升了网络的健壮性和拥塞控制的准确性。它帮助发送方避免因为网络抖动(乱序)而误判为网络拥塞,从而维持了更高的吞吐量。

总结:

机制 核心作用 触发条件 优点 缺点
超时重传 兜底保障 RTO 计时器超时 绝对可靠,应对严重网络问题 等待时间长,效率低
快速重传 加速恢复 收到 3 个重复 ACK 减少等待,提升效率 无法处理多包丢失,可能误判
SACK 精准重传 快速重传 + SACK 选项 只重传丢失的包,效率极高 增加协议复杂度和开销
D-SACK 网络诊断 收到重复数据包 避免误判拥塞,优化流控 增加协议复杂性

这四种机制共同构成了一个智能、高效的 TCP 重传体系:

  1. 快速重传 优先于 超时重传 触发,以应对偶发丢包。
  2. SACK 在快速重传的基础上,让重传更加精准。
  3. D-SACK 则在重传发生后,帮助发送方进行"事后分析",优化未来的传输策略。
  4. 如果以上所有机制都失效(例如网络完全中断),最终的 超时重传 机制将作为最后的保障来恢复连接。
相关推荐
大卡片2 小时前
IO缓存区
linux·运维·缓存
出海干货炒鱿鱼2 小时前
IP大科普:住宅IP、机房IP、原生IP、双ISP
运维·服务器
somi72 小时前
ARM-驱动-03 Linux 字符设备驱动开发
linux·arm开发·驱动开发·自用
CDN3602 小时前
高防服务器带宽跑满、业务掉线?流量限制与清洗优化
运维·服务器
似水এ᭄往昔2 小时前
【Linux】--程序地址空间
linux·运维·服务器
howe88882 小时前
搭建dcmtk的demo服务器
服务器·dicom
云飞云共享云桌面2 小时前
8-10位研发3D(sw、ug、creo)画图如何共享一台工作站?
运维·服务器·网络·数据库·3d·电脑
天启HTTP2 小时前
HTTP代理和隧道代理的底层区别与适用场景分析
开发语言·网络协议·tcp/ip·php
DeeplyMind2 小时前
Linux 内核补丁提交(Upstream)完整指南
linux·upstream