4. TCP 如何保证可靠传输(热度 310 · 高频选考)
Q: TCP 靠什么机制保证可靠?
A:
机制全景(四件套 + 两把窗口)
可靠性目标:数据无差错、不丢失、不重复、按序到达。
序号与确认(seq/ack)
- 每个字节都有序号;报文段首部
Sequence Number是本报文数据的首字节序号。 - 接收方用累积确认:
ack=N表示「N 之前的所有字节都已正确收到,期望下次从 N 开始」。 - TCP 对数据字节编号,不是「第几个包」。
- 每个字节都有序号;报文段首部
超时重传(Retransmission Timeout)
- 每个报文段有关联 RTO 定时器;超时未确认则重传。
- RTO 由 RTT 动态估算:
SRTT ← (1-α)SRTT + α*SampleRTT,RTO = SRTT + 4*RTTVAR。 - Karn 算法: 重传的 RTT 样本不可信(无法区分是对原包还是重传包的确认),要排除;RTO 退避(倍增)。
快速重传
- 连续收到 3 个重复 ACK 立即重传丢失段,不等超时。
- 省下的是整个 RTO 等待,不是"一个 RTT":凑齐 3 个重复 ACK 本身约要 1 个 RTT,而走超时路径要等 RTO —— 本机内核
include/net/tcp.h里TCP_RTO_MIN = HZ/5(CONFIG_HZ=1000→ 200ms 下界),初始 RTOTCP_TIMEOUT_INIT = 1*HZ(1s,RFC 6298 §2.1 的初始值 1s),上界TCP_RTO_MAX = 120*HZ(120s)。所以快重传把重传时延从数百毫秒~秒级压到 RTT 级,这才是它的收益量级。 - 重复 ACK 的含义:「我期望序号 X,但收到了 X 之后的数据」——中间有洞。
校验和
- 首部 + 数据的 16 位校验(含伪首部),检出比特错误则丢弃(等待重传)。
流量控制(rwnd)——面向接收方
- 接收方在 ACK 中通告窗口字段:「我还能收多少字节」。
- 接收缓冲区满 → 通告 0 窗口;发送方启动零窗口探测定时器。
拥塞控制(cwnd)——面向网络
- 根据网络拥塞程度调整发送速率(见第 6 题)。
- 实际发送窗口 = min(rwnd, cwnd)。
补充机制(深化)
- 乱序缓存: TCP 收到乱序段不丢弃,缓存并回重复 ACK 催缺口(更像 SR 而非 GBN)。
- 去重: 接收端按序号去重。
- 保活与 RST: 异常时用 RST 复位连接。
设计动机
- 为什么用累积确认而不是每包单独确认? 减少 ACK 数量、简化实现;配合快速重传与 SACK 可减轻「累计确认带来的模糊性」。
- 为什么快速重传门限是 3? 1 个重复 ACK 可能是乱序;连续 3 个说明后续多个包都到了但中间缺一块,更确信是丢包。
- 区分「可靠传输」与「拥塞控制」: 可靠面向接收方交付正确性;拥塞面向网络不被打垮。两者机制独立、最终窗口取 min。
常见追问
追问 1:TCP 收到乱序包会丢弃吗?和 GBN 什么关系?
- 答题要点: 不丢弃,缓存乱序段并发送重复 ACK,促使发送方快速重传缺口。更像选择重传 SR,而不是「丢弃一切乱序」的 GBN。笔试若问 GBN/SR 窗口上限是另一套题(补-03/04)。
追问 2:SACK 是什么?解决什么问题?
- 答题要点: Selective Acknowledgment,TCP 选项。接收方在 ACK 中告诉发送方「哪些非连续块已收到」,发送方只重传缺失段,避免累计确认导致的重复发送。需要双方协商开启。
追问 3:可靠传输 = 100% 不丢数据吗?
- 答题要点: TCP 提供的是在连接存续期间、网络最终能恢复的前提下的可靠字节流。若网络长期中断、应用崩溃、连接被 RST,仍可能失败。可靠性是传输层协议语义,不是分布式系统级的端到端 exactly-once。
易错点
| 易错说法 | 纠正 |
|---|---|
| 「ACK 确认的是包不是字节」 | TCP 对字节编号,ACK 是期望序号(累积) |
| 「可靠传输=拥塞控制」 | 可靠侧重序号/重传/校验;拥塞控制侧重网络速率,发送窗口取两者 min |
| 「超时与快速重传窗口变化一样」 | 超时:cwnd 回 1 重新慢开始;快速重传触发快恢复:cwnd 降到约一半 |
| 「TCP 从不缓存乱序」 | 会缓存,配合重复 ACK / SACK |
| 「校验和能纠错」 | 只检错;纠错靠重传 |
与选择题对照
- 主库 150: 第 59 题(端到端可靠传输)、第 66 题(流量控制目的)、第 67 题(发送窗口取决于)、第 68 题(3 个重复 ACK)、第 69 题(超时重传后 cwnd)、第 78 题(乱序报文段处理)、第 121 题(TCP/UDP 对比)。
- 补题 16: 补-03(GBN 窗口上限)、补-04(SR 窗口上限)、补-11(TCP 首部)。
- 口述联动: 选择题「乱序会怎样」答「缓存+重复 ACK」,与本题可靠传输机制直接衔接。
工程 / 抓包背景
- Wireshark:
tcp.analysis.duplicate_ack、tcp.analysis.retransmission、tcp.analysis.out_of_order、tcp.options.sack。 - ss:
ss -tin可看到rtt、cwnd、retrans、snd_wnd等 TCP 内部信息;注意 iproute2 没有名为rwnd的字段——「对端通告的接收窗口」在这里叫snd_wnd(uapitcpi_snd_wnd注释即 "peer's advertised receive window after scaling"),本端接收侧则是rcv_space/rcv_ssthresh;当发送被对端窗口卡住时还会多一个rwnd_limited:<ms>。 - sysctl:
net.ipv4.tcp_sack、net.ipv4.tcp_timestamps、net.ipv4.tcp_rmem/tcp_wmem。 - 现象: 大量 retransmission + RTT 抖动 → 网络丢包/缓冲膨胀;SACK 块多 → 非连续丢包;零窗口 → 接收方处理不过来(应用层消费慢)。