TCP 重传机制详解

概述

TCP 是一种可靠的传输协议,其核心目标之一就是确保数据能够准确无误地到达目的地。重传机制是实现这一目标的关键技术。当数据丢失或损坏时,TCP 通过重传机制来恢复数据,保证传输的可靠性。


1. 超时重传 (RTO)

1.1 基本原理

超时重传是 TCP 最基本的重传机制。其工作原理如下:

  1. 发送方发送数据段后,启动一个定时器(称为重传定时器 RTO)

  2. 如果在定时器超时前收到了对端的确认(ACK),则取消定时器

  3. 如果定时器超时仍未收到确认,则认为数据段丢失,重新发送该数据段

1.2 RTO 的计算

RTO(Retransmission TimeOut)不是固定值,而是动态计算的。TCP 使用 Karn 算法和 Jacobson/Karels 算法来动态调整 RTO:

```

SRTT = (1 - α) * SRTT + α * RTT_sample

RTTVAR = (1 - β) * RTTVAR + β * |RTT_sample - SRTT|

RTO = SRTT + max(G, 4 * RTTVAR)

```

其中:

  • SRTT:平滑往返时间(Smoothed RTT)

  • RTTVAR:RTT 变化量(RTT Variance)

  • α:平滑因子,通常为 1/8

  • β:变化量因子,通常为 1/4

  • G:时钟粒度,通常为 100ms

1.3 实际案例

**场景:** 客户端向服务器发送文件

```

时间线:

0ms -> 发送 Segment 1 (Seq=100, Size=1000)

100ms -> 收到 ACK (Ack=1100),RTO = 200ms

200ms -> 发送 Segment 2 (Seq=1100, Size=1000)

400ms -> 定时器超时!未收到 ACK

400ms -> 重传 Segment 2

500ms -> 收到 ACK (Ack=2100)

```

**问题分析:**

  • 第一次 RTT = 100ms,计算出 RTO = 200ms

  • Segment 2 在 200ms 发送,但可能由于网络拥塞丢失

  • 400ms 时定时器超时,触发重传

  • 重传后很快收到确认,说明数据确实丢失了

1.4 指数退避

每次超时重传后,RTO 会加倍(指数退避):

```

第1次超时:RTO = 200ms

第2次超时:RTO = 400ms

第3次超时:RTO = 800ms

第4次超时:RTO = 1600ms

...

```

这是为了避免在网络拥塞时过度发送数据,加剧网络负担。


2. 快速重传 (Fast Retransmit)

2.1 基本原理

快速重传是对超时重传的改进。它不依赖定时器超时,而是通过检测重复 ACK 来快速判断数据丢失。

**核心思想:** 如果收到 3 个重复的 ACK,说明后续数据已经到达,当前数据段很可能丢失了。

2.2 工作流程

```

发送方:

  1. 发送 Segment 1 (Seq=1)

  2. 发送 Segment 2 (Seq=101)

  3. 发送 Segment 3 (Seq=201)

接收方(Segment 2 丢失):

  1. 收到 Segment 1,回复 ACK=101

  2. 收到 Segment 3,期望 Seq=101,发现乱序

  3. 回复重复 ACK=101(告诉发送方期望收到 Seq=101)

  4. 继续收到后续数据,继续回复重复 ACK=101

发送方:

  1. 收到第1个重复 ACK=101

  2. 收到第2个重复 ACK=101

  3. 收到第3个重复 ACK=101 → 立即重传 Segment 2,无需等待超时

```

2.3 实际案例

**场景:** 视频流传输

```

发送方发送顺序:

Packet A (Seq=1) → Packet B (Seq=1001) → Packet C (Seq=2001) → Packet D (Seq=3001)

网络情况:Packet B 在传输中丢失

接收方:

  1. 收到 Packet A → ACK(1001)

  2. 收到 Packet C → 期望 Seq=1001,实际 Seq=2001,发送重复 ACK(1001)

  3. 收到 Packet D → 期望 Seq=1001,实际 Seq=3001,发送重复 ACK(1001)

  4. 收到 Packet E → 期望 Seq=1001,实际 Seq=4001,发送重复 ACK(1001)

发送方:

  • 连续收到 3 个 ACK(1001)

  • 立即重传 Packet B,无需等待 RTO(假设 RTO=200ms)

  • 节省了大约 200ms 的等待时间

```

2.4 快速重传的优势

| 对比项 | 超时重传 | 快速重传 |

|-------|---------|---------|

| 检测延迟 | RTO 时间(通常 200ms+) | 3 个重复 ACK(通常 < 100ms) |

| 适用场景 | 数据完全丢失 | 数据乱序或部分丢失 |

| 响应速度 | 较慢 | 快速 |


3. SACK(选择性确认)

3.1 问题背景

传统的累积确认(Cumulative ACK)存在一个问题:当多个数据段丢失时,发送方只能知道第一个未确认的数据段,无法知道后续哪些数据已经到达。

**例子:**

```

发送方发送:Seg1, Seg2, Seg3, Seg4, Seg5

接收方收到:Seg1, Seg3, Seg4, Seg5(Seg2 丢失)

传统 ACK:只能回复 ACK=Seg2的Seq(表示期望收到Seg2)

发送方不知道:Seg3, Seg4, Seg5 是否到达

结果:发送方可能会重传 Seg2, Seg3, Seg4, Seg5(冗余重传)

```

3.2 SACK 的解决方案

SACK(Selective Acknowledgment)允许接收方显式告知发送方哪些数据段已经成功接收,即使它们是不连续的。

**TCP 选项格式:**

```

Kind=5, Length=变量

+--------+--------+--------+--------+

| Kind=5 | Length | LeftEdge| RightEdge| ...

+--------+--------+--------+--------+

```

3.3 实际案例

**场景:** 文件传输,Seg2 和 Seg4 丢失

```

发送方发送顺序:

Seg1 (1-1000), Seg2 (1001-2000), Seg3 (2001-3000), Seg4 (3001-4000), Seg5 (4001-5000)

接收方收到:Seg1, Seg3, Seg5

Seg2 和 Seg4 丢失

传统 ACK:只能回复 ACK=1001

发送方行为:重传 Seg2, Seg3, Seg4, Seg5(冗余)

SACK 方式:

接收方回复:ACK=1001, SACK=[(2001-3000), (4001-5000)]

表示:

  • 期望收到 Seq=1001(Seg2)

  • 已收到 Seg3(2001-3000)

  • 已收到 Seg5(4001-5000)

发送方行为:只重传 Seg2 和 Seg4

```

3.4 SACK 的优势

```

传统方式:

发送: [Seg1] [Seg2] [Seg3] [Seg4] [Seg5]

收到: [Seg1] [---] [Seg3] [---] [Seg5]

ACK: ACK=1001

重传: [Seg2] [Seg3] [Seg4] [Seg5] ← 冗余!

SACK 方式:

发送: [Seg1] [Seg2] [Seg3] [Seg4] [Seg5]

收到: [Seg1] [---] [Seg3] [---] [Seg5]

ACK: ACK=1001, SACK=[Seg3, Seg5]

重传: [Seg2] [Seg4] ← 精准!

```


4. D-SACK(重复 SACK)

4.1 问题背景

SACK 可以告诉发送方哪些数据已收到,但无法区分:

  • 数据段是第一次到达

  • 数据段是重传后到达(可能因为原始数据段延迟到达)

**场景:** 网络延迟导致重复数据

```

发送方:

  1. 发送 Seg1,超时重传 Seg1

  2. 原始 Seg1 和重传 Seg1 都到达接收方

  3. 接收方收到重复数据,但发送方不知道

问题:发送方可能误以为数据仍未到达,继续重传

```

4.2 D-SACK 的解决方案

D-SACK(Duplicate SACK)扩展了 SACK,允许接收方标记重复收到的数据段。

**D-SACK 标志:**

  • SACK 块的 Left Edge = Right Edge - 1,表示这是一个重复确认块

4.3 实际案例

**场景:** 网络延迟导致重复

```

时间线:

T0: 发送方发送 Seg1 (Seq=1-1000)

T100: RTO 超时,重传 Seg1

T150: 原始 Seg1 到达接收方

T160: 重传 Seg1 到达接收方

接收方处理:

T150: 收到 Seg1 → ACK=1001

T160: 收到重复 Seg1 → ACK=1001, SACK=[(1-1000)] ← D-SACK

发送方处理:

收到 ACK=1001, SACK=[(1-1000)]

发现 SACK 块表示已经收到过 Seq=1-1000

推断:原始 Seg1 延迟到达,不是丢失

行为:停止重传,不调整 RTO

```

4.4 D-SACK 的应用场景

```

场景1:重复数据检测

发送: Seg1 → 超时重传 Seg1 → 两者都到达

D-SACK: 告诉发送方收到重复,避免继续重传

场景2:网络拥塞诊断

如果发送方频繁收到 D-SACK,可能说明:

  • 网络存在严重延迟

  • 路由抖动(数据走不同路径)

  • 可以作为拥塞控制的参考信号

场景3:RTO 调整优化

收到 D-SACK 后,发送方知道不是真正丢失

可以避免不必要的 RTO 指数退避

```


5. 乱序重传

5.1 乱序的原因

网络中数据乱序到达的常见原因:

  1. **多路径路由**:数据通过不同路径到达

  2. **队列调度**:路由器队列调度策略导致顺序变化

  3. **链路拥塞**:部分数据被延迟

5.2 乱序的处理

**接收方的乱序处理策略:**

```

接收缓冲区: [Seg1][---][Seg3][Seg4][---][Seg6]

↑ ↑

已确认 期望位置

处理方式:

  1. 保存乱序数据到接收缓冲区

  2. 发送重复 ACK 告知发送方期望的 Seq

  3. 等待缺失的数据段到达

  4. 连续数据到达后,一次性确认

```

**发送方的乱序处理策略:**

```

收到重复 ACK 时:

  • 1-2 个重复 ACK:可能只是轻微乱序,等待

  • 3 个重复 ACK:触发快速重传

  • 结合 SACK:精准判断哪些需要重传

```

5.3 实际案例

**场景:** 多路径传输

```

网络拓扑:

发送方 ──路径A── 路由器1 ──路径C── 接收方

└─路径B── 路由器2 ──路径D──┘

发送顺序:Seg1, Seg2, Seg3

传输情况:

Seg1 → 路径A→C(延迟 50ms)

Seg2 → 路径B→D(延迟 150ms)

Seg3 → 路径A→C(延迟 60ms)

接收顺序:

T50: Seg1 到达 → ACK=Seg2_Seq

T60: Seg3 到达(乱序)→ ACK=Seg2_Seq(重复ACK)

T150: Seg2 到达 → ACK=Seg4_Seq(累积确认)

```


6. 重传机制对比总结

| 机制 | 触发条件 | 优势 | 劣势 | 典型场景 |

|-----|---------|------|------|---------|

| 超时重传 | RTO 定时器超时 | 简单可靠 | 延迟高(RTO时间) | 数据完全丢失 |

| 快速重传 | 3 个重复 ACK | 响应快 | 需要收到后续数据 | 数据乱序或部分丢失 |

| SACK | 支持 SACK 选项 | 精准重传 | 需要双方支持 | 多段丢失场景 |

| D-SACK | 收到重复数据 | 避免重复重传 | 协议复杂度增加 | 网络延迟抖动 |


7. 实际应用中的配置

7.1 Linux 系统参数

```bash

查看当前 TCP 重传相关参数

sysctl -a | grep tcp | grep -E "(rto|retrans|sack)"

关键参数说明:

tcp_sack = 1 # 启用 SACK

tcp_dsack = 1 # 启用 D-SACK

tcp_fastopen = 3 # 启用快速打开

tcp_retries2 = 15 # 最大重传次数

tcp_syn_retries = 6 # SYN 包重传次数

```

7.2 常见调优场景

```

场景1:低延迟要求(如高频交易)

  • 降低初始 RTO(但可能增加重传次数)

  • 启用 TCP Fast Open

  • 使用 BBR 拥塞控制

场景2:长距离传输(如跨洲际)

  • 增大初始 RTO

  • 启用 SACK/D-SACK

  • 调整 TCP 窗口大小

场景3:无线网络(如 5G)

  • 增加最大重传次数

  • 启用 D-SACK(处理链路抖动)

  • 使用 TCP HyStart++

```


8. 总结

TCP 的重传机制是一个复杂而精妙的系统:

  1. **超时重传**提供了最基本的保障,是最后的兜底方案

  2. **快速重传**通过检测重复 ACK 实现快速响应

  3. **SACK** 解决了累积确认的局限性,实现精准重传

  4. **D-SACK** 解决了重复数据的问题,优化了 RTO 调整

  5. **乱序处理**确保了在复杂网络环境下的可靠性

这些机制相互配合,使得 TCP 能够在各种网络条件下提供可靠的数据传输,是互联网稳定运行的基石。

相关推荐
随便做点啥11 小时前
Intel Arc B60 Qwen3-Omni-30B-A3B 压测报告
服务器·经验分享
北京耐用通信11 小时前
耐达讯自动化:专业解决MODBUS TCP转PROFIBUS协议转换难题
人工智能·物联网·网络协议·自动化·信息与通信
2401_8734794011 小时前
主流IP离线库(IP数据云、纯真、IPIP.NET)怎么选?全面对比分析
服务器·网络·数据库
Harm灬小海12 小时前
【云计算学习之路】学习Centos7系统-Linux下用户及组管理
linux·运维·服务器·学习·云计算
herinspace12 小时前
管家婆辉煌主机登录提示“连接失败,请确认输入正确的服务器名”
运维·服务器·学习·零售·管家婆软件·财务软件
日取其半万世不竭12 小时前
Linux 云服务器磁盘扩容:从分区到文件系统的完整流程
java·linux·服务器
奋斗的小青年I12 小时前
虚拟化平台横评:Proxmox vs XCP-ng vs OpenStack vs Nutanix
网络·vmware·虚拟化·pve·超融合、
REDcker12 小时前
QUIC协议详解2
网络
yqcoder12 小时前
拆解互联网:通俗易懂的网络分层模型
前端·网络·网络协议