Skip to content

TCP 可靠传输与序号机制

考情分析

TCP 可靠传输机制是 408 的核心考点。选择题常考序号/确认号的计算、超时重传的触发条件;大题可能结合滑动窗口和拥塞控制一起考。SACK 偶尔在选择题中出现。

考频:★★★★

TCP 实现可靠传输的手段

IP 层提供的是不可靠的服务——数据可能丢失、乱序、出错、重复。TCP 在这个基础上通过以下机制实现可靠传输:

  1. 字节编号与确认:每个字节都有编号,接收方通过确认号告知发送方哪些数据已收到
  2. 超时重传:发送方在一定时间内未收到确认,自动重传
  3. 校验和:检测传输过程中的比特差错
  4. 滑动窗口:控制发送速率,配合流量控制和拥塞控制

字节流编号

TCP 把要发送的数据看作一个字节流,每个字节都有一个编号。报文段首部的序号字段(seq)存放的是该报文段数据部分第一个字节的编号。

举例:假设初始序号 seq=1,第一个报文段携带 100 字节(字节 1~100),则:

  • 第一个报文段:seq=1
  • 第二个报文段:seq=101
  • 第三个报文段:seq=201

序号空间是 02321(约 42.9 亿),用完后回绕到 0 重新开始。按照千兆以太网的速率,大约 34 秒就能用完一轮,所以高速网络中会使用时间戳选项来区分新旧序号。

确认号的含义

确认号 ack 表示期望收到的下一个字节的编号。也就是说,确认号之前的所有字节都已正确收到。

这是一种累积确认(Cumulative Acknowledgment)机制:如果接收方发送 ack=501,意味着字节 1~500 全部收到了。即使中间有些确认丢失了,只要最后一个确认到达发送方,发送方就知道前面的数据都收到了。

累积确认的优点是简单、容错性好;缺点是不够精确——如果字节 1~500 和 601~700 都收到了,但 501~600 丢失,接收方只能发送 ack=501,发送方不知道 601~700 已经收到了。

超时重传

发送方每发送一个报文段,就启动一个重传计时器。如果在计时器超时之前收到了确认,就撤销计时器;如果超时仍未收到确认,就重传该报文段。

超时重传时间(RTO)的设定

RTO 的设定是一个关键问题:

  • 设得太短:可能导致不必要的重传(数据还在路上,ACK 还没回来就重传了)
  • 设得太长:丢包后等待时间过久,影响传输效率

TCP 使用自适应算法来计算 RTO,基于对 RTT(往返时间)的测量。

加权平均 RTT 的计算:

RTTs=(1α)×RTTs+α×RTTsample

其中 α 的推荐值为 1/8RTTs 是平滑后的 RTT 估计值,RTTsample 是最新一次测量的 RTT。

RTT 偏差的计算:

RTTD=(1β)×RTTD+β×|RTTsampleRTTs|

其中 β 的推荐值为 1/4

RTO 的计算:

RTO=RTTs+4×RTTD

Karn 算法

有一个问题:如果报文段被重传了,收到的 ACK 到底是对原始报文段的确认还是对重传报文段的确认?无法区分。

Karn 算法的处理方式:对于重传的报文段,不采用其 RTT 样本来更新 RTT 估计值。同时,每次重传时将 RTO 翻倍(指数退避),直到收到未经重传的报文段的确认后,才恢复正常的 RTO 计算。

选择确认 SACK

累积确认有一个问题:接收方收到了不连续的数据块时,发送方不知道哪些已经收到了,可能会重传已经收到的数据。

SACK(Selective Acknowledgment,选择确认)通过 TCP 首部的选项字段,让接收方告知发送方哪些数据块已经收到了,从而让发送方只重传真正丢失的部分。

SACK 选项中列出接收方已收到的不连续的数据块边界。每个数据块用一对 32 位的序号表示(左边界和右边界),每对占 8 字节。由于 TCP 选项总长度最多 40 字节,刨去 2 字节的 SACK 选项头,最多能报告 (402)/8=4 个数据块。

示例:接收方收到了字节 1~500 和 601~800,缺少 501~600。

  • 累积确认:ack=501
  • SACK 附加信息:已收到 [601, 801)

发送方收到这个信息后,只需要重传 501~600,而不是 501~800。

TCP 的滑动窗口

TCP 的滑动窗口和数据链路层的滑动窗口原理类似,但有几个关键区别:

对比项数据链路层TCP
窗口单位字节
窗口大小固定动态调整(受 rwnd 和 cwnd 约束)
确认方式逐帧确认或累积确认累积确认(+ 可选 SACK)
编号空间较小(如 3 位 = 0~7)32 位(02321

TCP 发送方窗口结构

发送方维护的数据可以分为四个区域:

已确认 | 已发送未确认 | 可以发送 | 不能发送
       ← 发送窗口 →
  • 已确认:ack 之前的字节,已被确认
  • 已发送未确认:在发送窗口内,已发出但还没收到 ACK
  • 可以发送:在发送窗口内,但还没发出
  • 不能发送:发送窗口之外,需要窗口向右滑动后才能发送

发送窗口的大小:

发送窗口=min(cwnd,rwnd)

每收到一个确认,窗口的左边界向右移动(已确认的数据移出窗口),窗口可能会向右扩展。

交互可视化

加载可视化中...

易错点

1. 确认号是"期望收到的下一个",不是"已收到的最后一个"

收到了字节 1~500,确认号是 501 而不是 500。这个差一的问题经常出错。

2. 超时重传不意味着数据一定丢了

可能只是 ACK 丢了,或者 RTT 波动导致 RTO 设得太短。重传后,接收方可能会收到重复的数据,TCP 通过序号来丢弃重复数据。

3. 累积确认可能导致不必要的重传

如果报文段 1、2、3 中的 2 丢失了,接收方即使收到了 3,也只能发送 ack= 报文段 2 的起始序号。发送方可能会重传 2 和 3,尽管 3 已经收到了(如果不支持 SACK)。

4. 滑动窗口的大小不是固定的

TCP 的滑动窗口会根据流量控制(rwnd)和拥塞控制(cwnd)动态调整,不像某些数据链路层协议的窗口是固定的。

高频考点清单

  • 序号 = 报文段数据部分第一个字节的编号
  • 确认号 = 期望收到的下一个字节的编号(累积确认)
  • 超时重传时间 RTO 的计算公式:RTO=RTTs+4×RTTD
  • SACK 的作用和最多能报告 4 个不连续数据块
  • TCP 滑动窗口与数据链路层滑动窗口的区别
  • 发送窗口 = min(cwnd, rwnd)

真题练习

相关真题(5题)

2021Q40选择题2分

TCP 发送窗口计算:已发送未确认 200B + 可用窗口,序号范围 701~1000

2020Q38选择题2分

TCP 快速重传:收到 3 个重复 ACK 后立即重传

2013Q39选择题2分

TCP 序号与确认号计算:确认号=收到序号+数据长度

2011Q40选择题2分

TCP 累积确认:第2段丢失,只能确认到第1段末尾,确认号=200+300=500

2009Q38选择题2分

TCP 确认号计算:确认号 = 第一个段序号 + 两段总长度