摘要

  • 零接收窗口是接收方对新字节的有效暂停指令。它描述流量控制能力,并不证明主机、路径或应用已经故障。
  • 重新开放窗口往往只靠一条纯 ACK,而纯 ACK 不受可靠重传保护。发送方必须以小型探测重新询问,并对后续探测指数退避。
  • 只要接收方继续确认探测,TCP 就必须允许连接保持;但应用或操作系统仍可依照明确的资源政策主动终止。

死锁来自两次正确的沉默

接收应用停止读取,缓冲区逐渐填满,TCP 通告零窗口。发送方据此停发新数据。后来应用腾出空间,接收 TCP 发出带正窗口的 ACK。若这条包丢失,发送方手里仍是“零”;接收方却可能认为自己已经发过新许可。

RFC 1122 点明关键:不带数据的 ACK 并不由 TCP 可靠传输。于是,暂停通知可以正确,重开通知也可以正确发出,连接仍会因为一条许可消息丢失而无限等待。可靠性不能只保护数据,还必须保护发送权的变化。

窗口是容量,不是病历

RFC 813 区分接收方通告的 offered window 与发送方扣除在途未确认数据后得到的 usable window。这个数回答“现在还能收多少”,不回答“为什么没有继续读”。

标准沿用的例子是一台缺纸的打印机。应用可能停几分钟、几小时甚至几天,主机与网络仍然正常。若传输层仅凭零窗口就关闭连接,它等于替应用解释了一个自己看不见的业务状态。

接收窗口也不是拥塞窗口。前者保护终点缓冲区,后者约束路径负荷。路径畅通时接收方仍可能没有空间;接收方空间充足时网络也可能拥塞。两个控制面不能互相冒充。

一个例外字节重新询问事实

RFC 793 建立原始机制;现行汇编规范 RFC 9293 仍要求零窗口探测。发送方即使看到窗口为零,也要定期发送至少一个新字节(若有)或重传;接收方则用 ACK 回报当前期望序列与窗口。

这不是绕过零窗口偷偷发送正常数据。探测是一个受限问题。若窗口仍为零,ACK 重新确认暂停;若窗口已经打开,ACK 就把先前丢失的许可再送一次。

第一次探测应在零窗口持续一个重传超时后发出;此后间隔应指数增长。这样,单次丢包不会造成长久停顿,真正的长期暂停也不会遭到高频轮询。标准没有为所有应用规定同一个最大等待值。

已确认的零与无人回应不是同一证据

RFC 1122 允许接收 TCP 无限期维持零窗口。只要它继续确认探测,发送 TCP 就必须允许连接保持开放。

ACK 只能证明远端 TCP 与一条返回路径在当下作出了窗口报告。它不能证明远端进程健康、马上会读取,或本地继续占用队列仍然划算。不过,它仍强于沉默:无人回应意味着路径或对端不确定;确认零则是对端存在、但暂扣容量的积极证据。

坚持不等于出让本机内存

“可以无限期关闭”一度被误读为系统不得清理资源。RFC 6429 没有推翻传输语义,而是把权限边界说清楚:TCP 不应仅因处于 persist 自行宣判失败;应用或操作系统可以要求终止,TCP 必须执行。

这份文档也展示反向风险。大量客户端请求大响应后停止读取,持续通告零窗口,并可靠确认每次探测。服务器只需遵守 TCP,就可能长期保留发送队列和连接控制块,最终挤掉正常用户。

统一的隐藏超时无法区分合法的打印任务与廉价的资源占用。知道租户、承诺、队列成本和期限的那一层,才应拥有清理权。TCP 维护共享事实,本地政策承担本地代价。

把窗口一小口一小口打开,也会形成稳定故障

RFC 813 把细小窗口增量反复驱动小报文的模式称为 Silly Window Syndrome。它会增加 ACK、CPU 开销、丢包与重传;文档记录的严重数字是历史现场例子,不是所有网络的常数。

接收方可以暂不通告少量释放,等到空间足够有用时再一次打开。发送方也不必对每次微小右移立即发送。RFC 9293 要求两端都具备 SWS 避免算法,并说明 Nagle 处理的是应用小写入,二者互补而不相同。

Persist 保证一次有意义的重开不会因 ACK 丢失而消失;SWS 避免则阻止每一小块空闲都变成低效许可。可靠性与颗粒度共同决定窗口机制能否工作。

最小共享机制保留了本地选择

历史链条从 RFC 793,经 RFC 813 的性能分析、RFC 1122 的主机要求、RFC 6429 的资源权力澄清,进入 RFC 9293 的现行汇编。留下来的核心不是某个秒数,而是责任划分。

接收方控制当前容量;发送 TCP 用稀疏探测恢复容量变化;应用与操作系统决定等待需要付出多少时间、内存和服务机会。TCP 学会在零窗口里坚持,却没有许诺不计成本地等待。

来源与证据边界

闭合来源为 RFC 793、RFC 813、RFC 1122、RFC 6429 与 RFC 9293。它们不能证明每个系统的现实定时器、攻击普遍程度或某个应用是否健康。