Appearance
TCP 流量控制
考情分析
TCP 流量控制在 408 中属于中高频考点,常与拥塞控制结合出题。选择题考查流量控制与拥塞控制的区别、零窗口的处理方式;大题可能要求分析窗口变化过程。
考频:★★★★
流量控制的基本概念
流量控制要解决的问题很直接:发送方发得太快,接收方来不及处理。
如果发送方的发送速率远大于接收方的处理速率,接收方的缓冲区就会溢出,数据就会丢失。流量控制就是让发送方的发送速率不要超过接收方的处理能力。
TCP 使用滑动窗口机制来实现流量控制。接收方通过 TCP 首部的窗口字段告知发送方自己当前的接收窗口大小 rwnd(receiver window),发送方据此调整发送窗口。
接收窗口 rwnd
接收方根据自己的缓冲区空闲空间来设置 rwnd 的值,并在每一个 ACK 报文段中将 rwnd 通告给发送方。
发送方的发送窗口取 rwnd 和 cwnd 的较小值:
如果只考虑流量控制(不考虑拥塞控制),发送窗口 = rwnd。
窗口动态调整过程
通过一个具体的例子来理解窗口的动态调整。
假设 A 向 B 发送数据,B 的接收缓冲区大小为 400 字节。
| 步骤 | A 的操作 | B 的操作 | B 通告的 rwnd |
|---|---|---|---|
| 1 | 发送 100 字节 (seq=1) | 收到,缓冲区剩 300 | rwnd=300 |
| 2 | 发送 100 字节 (seq=101) | 收到,缓冲区剩 200 | rwnd=200 |
| 3 | 发送 100 字节 (seq=201) | 收到,缓冲区剩 100 | rwnd=100 |
| 4 | — | 应用层读走 200 字节,缓冲区剩 300 | rwnd=300 |
| 5 | 发送 100 字节 (seq=301) | 收到,缓冲区剩 200 | rwnd=200 |
可以看到,rwnd 不是单调递减的。当接收方的应用层从缓冲区读取数据后,rwnd 会增大。
零窗口问题
当接收方的缓冲区满了,rwnd = 0,接收方会发送一个零窗口通告。发送方收到后必须停止发送数据。
问题来了:如果接收方后来腾出了空间,发送了一个 rwnd > 0 的通告,但这个通告报文段丢失了,那就死锁了——A 等 B 说可以发了,B 等 A 发数据过来。
持续计时器
TCP 为了解决这个问题,设置了持续计时器(Persistence Timer)。
工作方式:
- 当发送方收到零窗口通告后,启动持续计时器
- 计时器到期时,发送方发送一个零窗口探测报文段(仅携带 1 字节数据)
- 接收方收到探测报文后,回复当前的窗口大小
- 如果窗口仍为 0,发送方重置计时器继续等待
- 如果窗口不为 0,发送方恢复正常发送
零窗口探测报文段虽然只有 1 字节,但它打破了死锁的可能性。
Nagle 算法
Nagle 算法解决的是小报文段过多的问题。如果应用层每次只产生 1 字节数据(比如 Telnet 的键盘输入),每个字节都单独发送的话,1 字节数据 + 20 字节 TCP 首部 + 20 字节 IP 首部 = 41 字节,开销比例极高。
Nagle 算法的规则:
- 第一个小报文段立即发送
- 后续的小数据先缓存起来,等到以下条件之一满足时再发送:
- 收到前一个报文段的确认
- 缓存的数据量达到 MSS
这样就把多个小数据合并成一个较大的报文段发送,减少了网络中小报文段的数量。
408 对 Nagle 算法的考查不深,知道它的作用和基本原理即可。
糊涂窗口综合症
糊涂窗口综合症(Silly Window Syndrome)是另一个和小报文段相关的问题,但它发生在接收方。
场景:接收方的缓冲区几乎满了,应用层每次只读取很少的数据(比如 1 字节),然后接收方就通告一个很小的窗口(比如 rwnd=1),发送方据此发送一个很小的报文段。如此反复,网络中充满了低效的小报文段。
解决方案(Clark 方案):接收方不要在窗口刚腾出一点空间时就立刻通告。而是等到:
- 缓冲区有足够大的空间(比如一半以上空闲),或者
- 能容纳一个 MSS 大小的报文段
才发送窗口更新通告。在此之前,继续通告 rwnd=0。
流量控制与效率的权衡
流量控制本质上是一种端到端的速率匹配机制。它在保护接收方不被淹没的同时,也可能限制传输效率。
考虑这样一个场景:接收方的应用层读取数据很慢(比如正在做复杂的计算),rwnd 会逐渐缩小,发送方被迫降低发送速率。即使网络本身没有拥塞,发送方也发不快——因为瓶颈在接收方的处理能力。
在 408 的大题中,如果同时给了 rwnd 和 cwnd,发送窗口 = min(cwnd, rwnd)。需要判断哪个是瓶颈:
- 如果 rwnd < cwnd:瓶颈在接收方(流量控制限制了发送速率)
- 如果 cwnd < rwnd:瓶颈在网络(拥塞控制限制了发送速率)
- 实际发送窗口总是取较小值
交互可视化
易错点
1. 流量控制和拥塞控制是两回事
流量控制是点对点的,防止发送方发得比接收方处理的快。拥塞控制是全局性的,防止网络过载。控制变量分别是 rwnd 和 cwnd。
2. 零窗口通告不是错误
零窗口是正常的流量控制行为,说明接收方缓冲区暂时满了。发送方收到后不是断开连接,而是启动持续计时器等待。
3. 持续计时器是发送方启动的
不是接收方。接收方只负责通告窗口大小,发送方负责在零窗口时主动探测。
4. rwnd 的单位是字节
TCP 首部窗口字段 16 位,表示的最大值是 65535 字节。如果需要更大的窗口,可以使用窗口缩放选项(Window Scale Option),这个选项在三次握手时协商。
5. 零窗口探测报文段也有重传计时器
如果零窗口探测报文段丢失了,发送方的持续计时器会再次超时,重新发送探测报文。这保证了即使探测报文丢失也不会永远死锁。
6. 发送窗口可能小于 rwnd
发送窗口 = min(cwnd, rwnd)。如果拥塞窗口 cwnd 比接收窗口 rwnd 小,那么发送窗口由拥塞控制决定,而不是流量控制。
高频考点清单
- 流量控制的目的:防止发送方发得比接收方处理的快
- rwnd 由接收方在每个 ACK 中通告
- 发送窗口 = min(cwnd, rwnd)
- 零窗口的处理:持续计时器 + 零窗口探测报文段
- 流量控制 vs 拥塞控制的区别(作用范围、控制变量、触发条件)
- Nagle 算法的作用(合并小报文段)
- 糊涂窗口综合症及其解决方案