TCP 是如何保证可靠传输的?
简化版
TCP 靠一套组合拳保证可靠:① 序列号给每个字节编号(保证有序、去重);**② 确认应答(ACK)**告诉发送方收到了哪里;③ 超时重传 + 快速重传补发丢失的数据;④ 校验和检测数据是否损坏;⑤ 流量控制防止发太快撑爆接收方;⑥ 拥塞控制防止发太快压垮网络。核心是「编号 + 确认 + 重传」。
详细版
TCP 保证可靠的六个机制:
- 序列号(Seq):给发送的每个字节编号。接收方据此排序(解决乱序)、去重(解决重复),并知道有没有缺口。
- 确认应答(ACK):接收方回复 ACK,告知「我已经连续收到了到某字节为止的数据」。TCP 用累计确认——ACK=n 表示 n 之前的都收到了。
- 超时重传:发送方发出数据后启动计时器,超时还没收到 ACK 就重发。超时时间(RTO)根据往返时延 RTT 动态计算。
- 快速重传:发送方连续收到 3 个重复 ACK,就不等超时,立即重传丢失的那个报文段(比等超时快)。
- 校验和(Checksum):首部和数据一起算校验和,接收方校验,出错就丢弃(等重传)。
- 流量控制 + 拥塞控制:滑动窗口控制发送速率,避免压垮接收方和网络(详见对应两道题)。
完整版教学
一、可靠传输的核心逻辑:编号 + 确认 + 重传
网络是不可靠的——数据可能丢失、乱序、重复、损坏。TCP 要在这样的网络上做出「可靠」,核心思路其实很朴素:
- 给每个字节编号(序列号) → 就能排序、去重、发现缺口;
- 收到就回确认(ACK) → 发送方知道哪些安全到达了;
- 超时/发现丢失就重发(重传) → 补上丢失的数据。
「编号—确认—重传」这个闭环是可靠传输的骨架,其余(校验和、流控、拥塞控制)都是围绕它的辅助。
二、累计确认与 SACK
TCP 默认用累计确认:ACK=1001 表示「1000 及之前的字节我都连续收到了,下一个我期待 1001」。它的好处是即使某个 ACK 丢了,后一个 ACK 也能覆盖确认,容错性好。
但累计确认有个短板:如果中间丢了一段、后面的都收到了,发送方从累计 ACK 里看不出「后面其实收到了」,可能重复重传。于是有了 SACK(选择性确认):接收方在 ACK 里额外告诉发送方「我还收到了 3000~4000 这段」,发送方就只重传真正缺失的部分,避免无谓重传。
三、超时重传 vs 快速重传
丢包后怎么触发重传,有两条路:
- 超时重传:发出数据就计时,RTO 到了还没等到 ACK 就重发。RTO 基于 RTT 动态估算(RTT 波动大就调大 RTO)。缺点是要等一段时间,慢。
- 快速重传:不干等超时。如果接收方收到失序的包,会重复发送上一个正确的 ACK。发送方一旦连续收到 3 个重复 ACK,就判断「中间那个包丢了」,立即重传,不等超时。
记住:3 个重复 ACK 触发快速重传,这是高频考点。它让常见的单包丢失能快速恢复,不必苦等 RTO。
四、为什么要动态计算 RTO
RTO(超时时间)不能写死:设太短,网络稍慢就误判丢包、重复重传,浪费带宽;设太长,真丢包了要等很久才补,卡顿。
所以 TCP 根据实测的 RTT(往返时延) 动态算 RTO:RTT 稳定就贴近 RTT,RTT 抖动大就留更多余量。重传的报文还会用指数退避(每重传一次 RTO 翻倍),避免在网络已经拥塞时火上浇油。
五、这些机制怎么协同
一次可靠传输里,多个机制同时在工作:
- 序列号 + 校验和保证「数据本身对」(有序、不重复、没损坏);
- ACK + 重传保证「丢了能补」;
- 流量控制保证「不撑爆接收方」;
- 拥塞控制保证「不压垮网络」。
前四个是「可靠」的直接手段,后两个是「可靠地、且不添乱地」把数据送达的速率控制。
六、常见误区
- ❌ 以为可靠就只是「丢了重传」——还包括排序、去重、校验、流控、拥塞控制一整套。
- ❌ 以为快速重传要等超时——它靠 3 个重复 ACK 提前触发,就是为了不等超时。
- ❌ 把流量控制和拥塞控制搞混——前者防撑爆接收方,后者防压垮网络(详见对应题)。
- ❌ 以为 RTO 是固定值——基于 RTT 动态计算,重传时指数退避。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| 序号 | 标识字节流位置,支持重排和去重 |
| 确认 | ACK 告诉发送端哪些数据已收到 |
| 重传 | 超时或重复 ACK 触发补发 |
| 校验和 | 发现传输中的比特错误 |
send seq=100 len=50
receiver ACK=150
timeout or 3 duplicate ACKs -> retransmit lost segment
TCP 可靠不是单靠一个机制,而是序号、确认、重传、窗口和校验共同工作。
- 误区:TCP 可靠表示数据永远不会丢。 网络中仍可能丢包,TCP 通过检测和重传让应用看到可靠有序字节流。
- 误区:ACK 是确认某一个报文。 常见累计 ACK 表示某个序号之前的字节都已收到。
- 误区:超时重传时间固定。 RTO 会根据 RTT 动态估算,固定值会在不同网络条件下过慢或误重传。
- 追问:快速重传依据什么? 收到多个重复 ACK 说明后续包到了但中间缺包,可不等超时先重传。
- 追问:SACK 有什么价值? SACK 能告诉发送端哪些不连续区间已收到,减少不必要重传。
- 追问:TCP 如何保证有序? 接收端按序交付给应用,乱序到达的数据会先缓存等待缺失部分。
七、加强记忆
TCP 可靠传输 = 序列号(排序去重)+ 确认应答(累计确认/SACK)+ 重传(超时重传 + 3 个重复 ACK 触发的快速重传)+ 校验和(检错)+ 流量控制(不撑爆接收方)+ 拥塞控制(不压垮网络)。核心骨架是「编号—确认—重传」,其余都是围绕它的保障。