摘要

  • RFC 2001 把连续三个重复 ACK 视为段丢失的强烈迹象,使发送端无需等到重传计时器到期即可补发疑似缺口。
  • 快速恢复先令 cwnd = ssthresh + 3 个段,随后每多一个重复 ACK 再加一个段;首个确认新数据的 ACK 到来时,cwnd 回落到 ssthresh。
  • 这些反馈只支持对接收前沿和在途数据的有限推断,不证明丢失原因、链路容量、对端身份、应用收件或后续交付。

第三次重复改变的是权限

第一次收到相同 ACK 时,发送端知道累计确认前沿没有前进,却不知道较早的段究竟丢了,还是只是落在后来段的后面。第二次重复仍然容得下重排序这一解释。RFC 2001 在第三次连续重复时跨过操作阈值:丢段已经是足够强的假设,可以不等 RTO 就重传那个看似缺失的段。

“足够强”不等于“已经证明”。文档假定,一般的重排序多半只产生一两个重复 ACK,迟到段随后会让累计确认号前移。数字三因此是把不完整观察转换成恢复动作的门槛,并不是窥见路由器队列的窗口。

从这里看,slow start、congestion avoidance、fast retransmit 和 fast recovery 并非四个平行术语,而是一条发送端状态链。未知路径先被小心探测,窗口随后缓慢增长;特定 ACK 模式触发提前重传,而仍在返回的重复 ACK 又说明数据流没有完全停止。

两扇窗口回答两个问题

接收端通告窗口回答“对端 TCP 还准备接收多少数据”。拥塞窗口 cwnd 回答“发送端依据所见网络状况,允许多少数据未获确认地留在途中”。RFC 2001 只允许发送两者中的较小值。接收缓存有空间,绝不等于中间路径有容量。

ssthresh 划分增长方式。低于阈值时,slow start 随确认新数据的 ACK 快速打开窗口;高于阈值时,congestion avoidance 让窗口每个 RTT 大致只增一个段。若计时器超时,发送端缺乏数据仍在流动的证据,cwnd 会退到一个段。三个重复 ACK 提供的情形不同:前沿未动,但后续段确实在对端出现。

重复 ACK 是一张受限收据

RFC 1122 允许接收端在一个有效段落入接收窗口、却不在左边沿时立即发送 ACK。这个 ACK 继续报告 RCV.NXT,也就是仍然期待的下一个序号。它同时留下两条有限事实:缺口尚未补齐,缺口之后的某个段已经抵达接收 TCP。

它没有报告缺口为何形成。拥塞丢弃、链路损坏、路径变化、正常重排序、反馈复制或接收端行为,都可能从发送端投下相似影子。三个重复 ACK 让“丢失”成为可行动推断,却不提供物理原因。

同理,它没有测出瓶颈位置、空队列大小、公平份额或未来吞吐量。把 DupACK 计数直接命名为“拥塞证明”,会把 RFC 自己保留的不确定性擦掉。

+3 是临时记账,不是新增容量

第三个重复 ACK 到来时,RFC 2001 先把 ssthresh 设为当前 cwnd 的一半,但不得小于两个段;再重传疑似缺失段;最后把 cwnd 设为 ssthresh + 3*segsize。

这三个段的增量来自一条推断:接收端只有收到另一个段,才会生成重复 ACK。因此,三个重复 ACK 分别代表三个后续段已经离开网络并缓存在接收端。临时膨胀是在修复缺口期间补回这些推定离开量,避免 ACK 时钟骤然断掉。

以后每多一个重复 ACK,cwnd 再增加一个段;只有新窗口确实容许,发送端才可发一个包。这里没有永久提速,也没有容量承诺。每张受限收据只借出一个临时位置。

新数据 ACK 收回借款

当下一个 ACK 开始确认新数据,RFC 2001 把 cwnd 直接设回 ssthresh。先前三个段和后续 DupACK 累积的膨胀全部消失。发送端保留的是丢失前大致一半的速率,进入 congestion avoidance,而不是像超时后那样从一个段重新 slow start。

文档预期,这个 ACK 会确认补发段以及缺口后的中间数据。预期仍不是全知。发送端看见累计前沿推进,却看不见哪一个副本沿哪条路径产生结果,也看不见应用进程是否读取、存储或完成业务动作。

窗口收缩是快速恢复不可省略的另一半。若只记录提前重传,却不记录额外额度何时收回,就把一次临时恢复授权误写成长期发送权。

不要把链条压成一个成功字段

可审计记录至少应分开保存:重复的 ACK 号、右窗口边沿、重复次数、未确认序号范围、事件前后的 cwnd 与 ssthresh、重传范围、临时膨胀放行的每个包、首次前移的 ACK,以及另行取得的应用层结果。

RFC 793 给出了最重要的上限:TCP ACK 只表示接收 TCP 已承担责任,不保证数据已经交给最终用户。重复 ACK 的含义更窄。它也不认证对端;RFC 2001 的安全考虑章节明确未讨论安全问题。

RFC Editor 信息页记录了作者 W. Richard Stevens 和 1997 年 1 月的发布状态,并标明本文档后来被 RFC 2581 取代。HTML、纯文本与 IETF 文档历史保存原始算法。RFC 1122解释乱序段 ACK,RFC 793限定确认语义;RFC 2581这里只作为状态沿革来源。

本文不声称现代协议栈逐字执行 RFC 2001,也不进入 RFC 5681、RACK、计时史或实现性能。它只复原一条历史控制链:收据、推断、临时许可、收回许可。