← 返回题目列表

TCP 零窗口是什么?为什么需要零窗口探测?

高频 困难 第 20 / 30 题 更新于 2026/07/30
TCP零窗口流量控制Persist Timer接收窗口

简化版

TCP 零窗口表示接收方通告 rwnd=0,告诉发送方接收缓冲区满了,暂时不要再发数据。为了避免窗口恢复通知丢失导致双方永久等待,发送方会启动 persist timer,周期性发送零窗口探测包。

详细版

零窗口是 TCP 流量控制的边界场景:

  1. 接收方应用读取太慢,内核接收缓冲区被占满,就会通告窗口为 0。
  2. 发送方看到 rwnd=0 后停止发送普通数据,避免压垮接收方。
  3. 如果接收方后来有空间,会通告新的窗口。
  4. 这个窗口更新报文也可能丢失,所以发送方不能无限等待。
  5. 发送方会用零窗口探测确认窗口是否恢复,避免死锁。

面试要强调:零窗口不是拥塞控制,而是接收方流量控制;零窗口探测解决的是“窗口更新丢失导致双方互等”的问题。

完整版教学

一、零窗口从哪里来

TCP 接收方有接收缓冲区。网络包到达后,内核先放入缓冲区,应用再通过 read 消费。如果应用读取速度慢于网络到达速度,缓冲区可用空间会越来越小,最终可能变成 0。

当可用空间为 0 时,接收方会在 ACK 中通告 rwnd=0。这不是说连接坏了,而是在做流量控制:告诉发送方“我现在没有地方放新数据”。

接收缓冲区 8KB:
已占用 8KB,可用 0KB
=> 通告窗口 rwnd = 0

记忆钩子:零窗口是接收方喊“先别发,我缓存满了”,不是网络说“我堵了”。

二、发送方收到零窗口后做什么

发送方收到 rwnd=0 后,不能继续按原速发送普通数据,否则接收方没有空间接收,只会造成无意义重传和缓存压力。它会暂停发送新数据,并等待接收方通告窗口恢复。

但已经发送未确认的数据仍然要按 TCP 可靠传输机制处理。零窗口只限制“新数据发送”,不代表连接状态进入关闭。

项目零窗口时的行为
新应用数据暂停发送
已发送未确认数据继续等待 ACK 或重传
ACK 报文仍可收发
连接状态通常仍是 ESTABLISHED

这个点很容易和连接断开混淆。零窗口可能让应用写入阻塞或发送缓冲区堆积,但它本身不是 FIN/RST。

三、为什么需要零窗口探测

设想一个场景:接收方缓冲区满了,通告 rwnd=0;过一会儿应用读走数据,接收方发送窗口更新 rwnd=4096;但这个窗口更新 ACK 在网络中丢了。此时接收方以为自己已经通知了,发送方以为窗口仍是 0,双方就可能一直等。

零窗口探测就是为了解这个死锁。发送方启动 persist timer,到时间后发送一个很小的探测段,迫使接收方回复当前窗口大小。

Receiver -> Sender: rwnd=0
Receiver 应用读取,窗口恢复到 4096
Receiver -> Sender: rwnd=4096  (丢失)
Sender 等待中...
Sender -> Receiver: zero window probe
Receiver -> Sender: ACK, rwnd=4096

四、零窗口和拥塞窗口有什么区别

零窗口来自接收方的 rwnd,属于流量控制;拥塞窗口 cwnd 来自发送方对网络拥塞程度的判断,属于拥塞控制。实际可发送数据受两者共同限制,但它们保护的对象不同。

可发送窗口 = min(rwnd, cwnd)

rwnd = 0, cwnd = 64KB  => 仍然不能发新数据
rwnd = 64KB, cwnd = 2KB => 只能谨慎发 2KB

如果线上看到零窗口,重点查接收端应用读取、CPU、GC、磁盘、下游阻塞,而不是先调拥塞控制参数。

五、零窗口会造成哪些线上表现

零窗口会让发送方数据堆在发送缓冲区,应用写入可能变慢或阻塞。对于 HTTP、数据库连接、消息系统等长连接协议,零窗口常常意味着对端应用处理不过来,或者某个线程卡住没有消费 socket。

现象可能含义排查方向
抓包出现 Win=0接收端缓冲区满看接收端应用是否读取
发送端写阻塞对端不再接收新数据看 socket buffer 和业务线程
周期性小包探测persist timer 工作判断窗口是否恢复
RTT 正常但吞吐为 0非网络拥塞查应用消费速度

举例:服务端生成响应很快,但客户端因为本地处理慢没有及时读取,客户端通告零窗口。服务端此时不是“网络发不出去”,而是被客户端流量控制按住了。

六、Silly Window Syndrome 和小窗口问题

零窗口恢复后,如果接收方每腾出几个字节就通告很小窗口,发送方每次也只发很小段,会造成大量小包,降低效率。这类问题叫 Silly Window Syndrome。

解决思路通常是避免过小窗口频繁通告,或者发送方等到有足够数据/窗口再发送。它和 Nagle、延迟 ACK 等机制有一定关联,但核心仍然是减少小包低效传输。

低效恢复:
rwnd=1 -> 发1字节
rwnd=2 -> 发2字节
rwnd=3 -> 发3字节

更合理:
等待窗口恢复到 MSS 或缓冲区较大比例后再发送

面试不必展开所有算法细节,但提到“小窗口会造成小包放大和吞吐下降”,会显得理解更完整。

七、常见误区与追问

  • 误区:零窗口说明网络拥塞。 零窗口来自接收端缓存不足,是流量控制,不是拥塞控制。
  • 误区:rwnd=0 后连接就断了。 连接仍可保持 ESTABLISHED,只是暂停发送新数据。
  • 误区:等待窗口恢复通知就够了。 窗口更新报文可能丢失,所以需要零窗口探测避免死锁。
  • 追问:零窗口探测发什么? 通常发送很小的探测段,让接收方回复当前窗口大小。
  • 追问:看到大量零窗口先查哪里? 优先查接收端应用是否及时 read,以及 CPU、GC、磁盘、下游依赖是否卡住。
  • 追问:零窗口和发送缓冲区满有什么关系? 对端零窗口会让本端新数据发不出去,本端发送缓冲区可能逐渐堆满。

八、加强记忆

零窗口按“满、停、探、复”记:接收缓冲区满,通告 rwnd=0;发送方停止新数据;persist timer 触发探测;窗口恢复后继续发送。答题时一定点出它是流量控制边界,不是拥塞控制或连接关闭。