Appearance
TCP 可靠传输与序号机制
考情分析
TCP 可靠传输机制是 408 的核心考点。选择题常考序号/确认号的计算、超时重传的触发条件;大题可能结合滑动窗口和拥塞控制一起考。SACK 偶尔在选择题中出现。
考频:★★★★
TCP 实现可靠传输的手段
IP 层提供的是不可靠的服务——数据可能丢失、乱序、出错、重复。TCP 在这个基础上通过以下机制实现可靠传输:
- 字节编号与确认:每个字节都有编号,接收方通过确认号告知发送方哪些数据已收到
- 超时重传:发送方在一定时间内未收到确认,自动重传
- 校验和:检测传输过程中的比特差错
- 滑动窗口:控制发送速率,配合流量控制和拥塞控制
字节流编号
TCP 把要发送的数据看作一个字节流,每个字节都有一个编号。报文段首部的序号字段(seq)存放的是该报文段数据部分第一个字节的编号。
举例:假设初始序号 seq=1,第一个报文段携带 100 字节(字节 1~100),则:
- 第一个报文段:seq=1
- 第二个报文段:seq=101
- 第三个报文段:seq=201
序号空间是
确认号的含义
确认号 ack 表示期望收到的下一个字节的编号。也就是说,确认号之前的所有字节都已正确收到。
这是一种累积确认(Cumulative Acknowledgment)机制:如果接收方发送 ack=501,意味着字节 1~500 全部收到了。即使中间有些确认丢失了,只要最后一个确认到达发送方,发送方就知道前面的数据都收到了。
累积确认的优点是简单、容错性好;缺点是不够精确——如果字节 1~500 和 601~700 都收到了,但 501~600 丢失,接收方只能发送 ack=501,发送方不知道 601~700 已经收到了。
超时重传
发送方每发送一个报文段,就启动一个重传计时器。如果在计时器超时之前收到了确认,就撤销计时器;如果超时仍未收到确认,就重传该报文段。
超时重传时间(RTO)的设定
RTO 的设定是一个关键问题:
- 设得太短:可能导致不必要的重传(数据还在路上,ACK 还没回来就重传了)
- 设得太长:丢包后等待时间过久,影响传输效率
TCP 使用自适应算法来计算 RTO,基于对 RTT(往返时间)的测量。
加权平均 RTT 的计算:
其中
RTT 偏差的计算:
其中
RTO 的计算:
Karn 算法
有一个问题:如果报文段被重传了,收到的 ACK 到底是对原始报文段的确认还是对重传报文段的确认?无法区分。
Karn 算法的处理方式:对于重传的报文段,不采用其 RTT 样本来更新 RTT 估计值。同时,每次重传时将 RTO 翻倍(指数退避),直到收到未经重传的报文段的确认后,才恢复正常的 RTO 计算。
选择确认 SACK
累积确认有一个问题:接收方收到了不连续的数据块时,发送方不知道哪些已经收到了,可能会重传已经收到的数据。
SACK(Selective Acknowledgment,选择确认)通过 TCP 首部的选项字段,让接收方告知发送方哪些数据块已经收到了,从而让发送方只重传真正丢失的部分。
SACK 选项中列出接收方已收到的不连续的数据块边界。每个数据块用一对 32 位的序号表示(左边界和右边界),每对占 8 字节。由于 TCP 选项总长度最多 40 字节,刨去 2 字节的 SACK 选项头,最多能报告
示例:接收方收到了字节 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 位( |
TCP 发送方窗口结构
发送方维护的数据可以分为四个区域:
已确认 | 已发送未确认 | 可以发送 | 不能发送
← 发送窗口 →- 已确认:ack 之前的字节,已被确认
- 已发送未确认:在发送窗口内,已发出但还没收到 ACK
- 可以发送:在发送窗口内,但还没发出
- 不能发送:发送窗口之外,需要窗口向右滑动后才能发送
发送窗口的大小:
每收到一个确认,窗口的左边界向右移动(已确认的数据移出窗口),窗口可能会向右扩展。
交互可视化
易错点
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 的计算公式:
- SACK 的作用和最多能报告 4 个不连续数据块
- TCP 滑动窗口与数据链路层滑动窗口的区别
- 发送窗口 = min(cwnd, rwnd)