零窗口与恢复机制
TCP 用通告窗口告诉对端「我还能接多少字节」。接收缓冲被写满、应用来不及读取时,接收端通告窗口 0,发送端必须停止发送,只能按退避周期发窗口探测。等应用把数据读走、缓冲释放,接收端发一个窗口更新把窗口放开,传输才继续。抓包看到的就是「窗口 0 通告 → 周期探测 → 窗口更新 → 数据恢复」这条链路。
基本信息
| 本质 | 接收侧流控:接收缓冲不足时暂停发送方 |
|---|---|
| 关键报文 | 窗口 0 通告、窗口探测、窗口更新 |
| Wireshark 过滤 | tcp.analysis.zero_window / window_probe / window_update |
| 内核相关 | 接收缓冲由 SO_RCVBUF / tcp_rmem 等参数决定(Linux) |
| 持续时间 | 取决于接收端应用何时读取,与网络无关 |
典型使用场景
- 长连接业务周期性卡顿,确认是否为接收侧缓冲打满
- 定位「服务端处理慢」的硬证据:窗口归零后发送方确实无包可发
- 评估大批量传输时接收缓冲是否需要调大
- 区分「网络丢包」与「应用读取慢」两类吞吐骤降
恢复链路
恢复链路
窗口为 0 的通告 # 接收端缓冲已满
发送端周期发窗口探测 # 按退避间隔,探测间隔逐步拉长
应用读取释放缓冲 # 接收端本地动作,抓包里看不到
窗口更新(数值大于 0) # 接收端通知可以继续发送
数据段重新出现 # 传输恢复分阶段报文特征
| 阶段 | 报文特征 | 动作方 |
|---|---|---|
| 通告归零 | 窗口字段等于 0 | 接收端 |
| 窗口探测 | 零载荷或单字节小包,间隔递增 | 发送端 |
| 窗口更新 | 窗口字段恢复为正值 | 接收端 |
| 恢复传输 | 正常数据段重新出现 | 发送端 |
零窗口持续过久时,中间设备可能因会话老化直接断开连接,长连接业务要同时关注中间设备超时配置。
抓包只能证明「慢在接收侧应用」,具体是 GC、锁竞争还是下游依赖阻塞,需要结合应用日志与线程状态。