注:本文基于模型知识整理,建议结合权威教材与 RFC 原文核对细节。
一句话定义
TCP 用「字节序号 + 累积确认 + 超时与快速重传 + 滑动窗口」的组合,在不可靠的 IP 之上实现不丢、不重、不乱序、最终有序的字节流交付。
为什么重要
可靠是 TCP 存在的理由,而确认与重传策略直接决定吞吐与时延:同一次丢包,走超时路径要等一个可能达秒级且指数退避的 RTO,走快速重传路径通常一个 RTT 内解决。理解滑动窗口与 RTO 估算,是解释跨洋传输慢、弱网卡顿等现象的钥匙,也是拥塞控制(kp-020)与内核调优(kp-021)的地基。
前置知识
建议先读 kp-018《TCP 连接管理:三次握手与四次挥手》,掌握序号、确认号与连接状态语义;文中涉及拥塞窗口之处参考 kp-020,无需预先精通。
核心概念
- 字节序号:TCP 的序号以字节为单位,报文段的 seq 是其所载第一个字节的编号。这一点与教材通用模型「按报文段编号」不同,读抓包时必须按字节换算。
- 累积确认(cumulative acknowledgment):确认号 = 期望收到的下一个字节,语义为「此前所有字节均已收妥」。收到失序(out-of-order)数据先缓存,并重复发送当前最高连续点的确认。
- 冗余 ACK(duplicate ACK):同一确认号被重复收到;对发送方而言,连续多个冗余 ACK 通常意味着其后某段丢失。
- 回退 N(Go-Back-N)与选择重传(Selective Repeat, SR):两种流水线策略。前者丢一段重传一串、接收端只需记一个期望序号;后者只补缺失、需按序号缓存乱序数据。TCP 以累积确认打底、行为偏向回退 N,再用 SACK(Selective Acknowledgment,RFC 2018 定义的选项)补上「已收到但未连续」的信息,只重传真正缺失的段。
公式与模型
RTO(Retransmission TimeOut,重传超时)按 RFC 6298 估计。每次取得 RTT 样本后更新:
SRTT = (1 − α)·SRTT + α·RTT,α = 1/8
RTTVAR = (1 − β)·RTTVAR + β·|SRTT − RTT|,β = 1/4
RTO = SRTT + 4·RTTVAR
其中 SRTT 为平滑往返时间,RTTVAR 为平滑往返偏差。Karn 算法:被重传的报文段不作为 RTT 样本——其 ACK 无法区分对应原始发送还是重传,计入会污染估计;发生重传时 RTO 指数退避加倍。
图示
发送窗口四分区(SendBase:已确认的最高字节号;NextSeq:下一个待发字节)
| 已发送且已确认 | 已发送未确认 | 可立即发送 | 不可发送 |
<-------------><------------><----------><--------->
^ ^ ^
SendBase NextSeq-1 窗口右边界(受 rwnd 与 cwnd 限制)
滑动:ACK 到达 → SendBase 右移 → 窗口整体右滑 → 新数据获得发送资格原理与机制
从停等(stop-and-wait)协议讲起:发一段、停下、等确认再发下一段,利用率 ≈ 传输时间 ÷(传输时间 + 2×传播时延),在长肥链路上趋近于零。出路是流水线化:不等确认连续发送多个报文段,代价是必须用窗口限制在途数据量,并选好重传策略——回退 N 机制简单但重传整串浪费带宽,选择重传省带宽却要更多缓存与状态。TCP 的现实选择是累积确认打底(偏向回退 N 行为),加 SACK 选项逼近选择重传。
两条重传路径。超时路径:RTO 到期仍无确认则重传该段,RTO 指数退避,重传段不采样 RTT(Karn 算法)。快速重传路径:连续收到 3 个冗余 ACK 立即重传缺失段,不等超时;阈值取 3 是为了过滤乱序重排造成的少量冗余 ACK 噪声。两条路径的搭配逻辑:超时往往意味着网络严重拥塞,处理须保守;冗余 ACK 说明 ACK 仍在正常返回、网络还通着,重传可以更激进,并由此衔接 kp-020 的快速恢复。
实例分析
设 RTT = 200ms 的链路,第 5 号报文段丢失,其后 4 个段陆续到达接收端:接收端把它们全部缓存进失序队列,对每一段都重复确认第 5 号;发送方收到第 3 个冗余 ACK 即触发快速重传,若开启 SACK 可精确得知缺失的仅第 5 号,只补这一段,全程约一个 RTT 完成。对比超时路径:要等 RTO 到期(估计值叠加指数退避,可达秒级量级),且无 SACK 时可能重传第 5 号之后的整串——同一丢包,两条路径的代价差出一个数量级。
常见误区
一,「确认号表示已收到多少字节」:它是期望的下一个字节号,累积语义,不能当作字节数直接使用。二,「乱序报文会被丢弃」:接收端缓存乱序数据并重复当前累积确认,不丢数据。三,「SACK 是独立协议」:它只是 TCP 首部里的选项字段,需双方协商开启,现代内核默认支持。四,「RTO 越小越好」:过小导致大量过早重传、浪费带宽并触发退避;RTO 的本质是在「重传太快」与「等待太久」之间做统计权衡。
自测题
- 确认号 10001 精确意味着什么?
答案要点: 字节 10000 及之前的全部数据已按序收妥,期望对方从 10001 开始发送;是累积确认,不代表恰好收到了多少字节。
- 快速重传为什么阈值是 3 个冗余 ACK 而不是 1 个?
答案要点: 乱序重排也会产生零星重复 ACK;连续 3 个才能区分重排噪声与真实丢包,在误报与及时性之间折中。
- Karn 算法解决什么问题、规则是什么?
答案要点: 重传段的 ACK 无法对应到原始发送还是重传,采样会污染 RTT 估计;规则是重传段不采样,且重传时 RTO 指数退避。
- 回退 N 与选择重传的核心取舍是什么?TCP 如何取舍?
答案要点: 前者接收端只需一个期望序号、缓存小,但丢一段重传一串;后者只补缺但要按序号缓存乱序数据。TCP 用累积确认打底偏向前者,SACK 选项补上已收信息逼近后者。
- 停等协议在长肥链路上的效率问题说明了什么?
答案要点: 利用率 ≈ 传输时间 ÷(传输时间 + 2×RTT),RTT 远大于传输时间时利用率趋零;说明可靠协议必须流水线化并以窗口控制在途量,吞吐 ≈ 窗口/RTT。
延伸阅读
- RFC 9293《Transmission Control Protocol (TCP)》可靠传输语义
- RFC 6298《Computing TCP's Retransmission Timer》
- RFC 2018《TCP Selective Acknowledgment Options》
- 谢希仁《计算机网络》(第 8 版)可靠传输与滑动窗口章节