Skip to content

TCP 拥塞控制

2026 大纲 五(三)5 TCP 拥塞控制。机制与推导在本篇;cwnd 的逐轮数值表与做题口径在《拥塞控制典型计算题》;网络层视角的开环/闭环控制与 AQM 在《网络层功能》。

一、为什么"加资源"解决不了拥塞

上一篇的 rwnd 管的是"对方接不接得下",这一篇的 cwnd 管的是"网络扛不扛得住"。

拥塞的定义式很短:对资源的需求>可用资源。这里的资源指链路容量(带宽)、交换节点中的缓存和处理机

直觉的第一反应是"那就加资源"。但加不出来。

把缓存扩到非常大、凡到达的分组都能排队,可输出链路的容量和处理机的处理速度并未提高,队列中绝大多数分组的排队时间大大增加,上层软件只好把它们全部重传——分组还在队列里排着,副本已经在路上了,缓存越大浪费越严重。提高处理机速率也一样,只会把瓶颈转移到别处

实质是整个系统各部分不匹配,只有所有部分都平衡了问题才解决。

更关键的是拥塞会自我恶化:缓存不够就丢弃新到的分组,源点于是重传甚至重传多次,引起更多分组流入又被丢弃。这条正反馈是理解全部设计的钥匙——既然重传会加剧拥塞,所有动作就必须朝"主动减少注入"去,不能只靠重传把数据补回来。

还有两句判断要按住:分组丢失是拥塞的征兆而不是原因;而且拥塞控制机制本身也可能成为性能恶化甚至死锁的原因——动作过频会使系统产生不稳定的振荡,过缓又不具实用价值。

拥塞控制与流量控制的分野在上一篇讲过,这里补上定性表述:拥塞控制是全局性过程(涉及所有主机、所有路由器及一切与降低网络传输性能有关的因素),变量 cwnd发送方自己维护;流量控制是点对点通信量的控制,是个端到端的问题(接收端控制发送端),变量 rwnd接收方通告。两者合起来定发送窗口:min(cwnd, rwnd)

吞吐量随提供的负载变化的四阶段曲线与教材原话(想看清曲线形状时展开)

横坐标是提供的负载(单位时间内输入给网络的分组数),纵坐标是吞吐量(单位时间内从网络输出的分组数)。

 吞吐量

   │            理想拥塞控制:饱和后保持水平
   │        ┌──────────────────────────
   │      ╱ │
   │    ╱   │      实际:轻度拥塞(增速变缓)
   │  ╱     └╌╌╌╌╌╌╮
   │╱              ╰╌╌╌╌╌╮  拥塞(吞吐量反而下降)
   │                     ╰╌╌╌╌╌╌╌╌╌╌╮
   │                                ╰╌╌► 死锁(吞吐量降到 0)
   └────────────────────────────────────────► 提供的负载
      45° 斜线段:吞吐量 = 提供的负载
阶段表现教材原话
未饱和吞吐量 = 提供的负载,是一条 45° 斜线"具有理想拥塞控制的网络,在吞吐量饱和之前,网络吞吐量应等于提供的负载"
轻度拥塞吞吐量增长变缓,已经有一部分输入分组被丢弃"当网络的吞吐量明显地小于理想的吞吐量时,网络就进入了轻度拥塞的状态"
拥塞吞吐量随负载增大反而下降"当提供的负载达到某一数值时,网络的吞吐量反而随提供的负载的增大而下降"
死锁吞吐量降到零,网络已无法工作"当提供的负载继续增大到某一数值时,网络的吞吐量就下降到零……这就是所谓的死锁"

二、发送方凭什么断定"网络堵了"

发送方身处端系统,看不到路由器队列,手里只有一条线索:确认有没有按时回来

推理链是:拥塞时路由器要把来不及处理的分组丢弃,因此只要出现了超时,就可以估计可能在网络某处出现了拥塞;成立的前提是因传输出差错而丢弃分组的概率很小(远小于 1%)

所以"超时 = 拥塞"是概率推断,不是逻辑必然。教材那句"就猜想……但这时却无法知道拥塞到底发生在网络的何处,也无法知道发生拥塞的具体原因"定下了全部基调——这是一套在信息严重不足的条件下工作的启发式算法,所以动作都很粗糙(翻倍、减半、置 1):精细控制需要的信息它根本拿不到。

这个判据在什么情况下会失效(想知道无线链路上 TCP 为什么吃亏时展开)

最典型的是无线链路:信道误码率高,丢包很可能是信号衰落造成的,网络根本不堵,TCP 却照样把 cwnd 减半甚至降到 1,在没有拥塞的网络上白白降速。这是传统 TCP 拥塞控制在无线环境下的经典短板。

另一种失效场景教材也提到了:路由器对某些分组的处理时间特别长导致发送方超时重传,"重传会使 TCP 连接的发送端认为在网络中发生了拥塞。于是在 TCP 的发送端就采取了拥塞控制措施,但实际上网络并没有发生拥塞"。

三、四种算法与两张规则表

慢开始与拥塞避免

慢开始的规则:每收到一个对新报文段的确认,cwnd 增加 min(N, SMSS)N 为被该确认新确认的字节数)。按轮次看即 1248 指数增长

"慢"指起点低,不指增长慢——参照系是"一上来就把窗口开到最大"。慢开始阶段的斜率恰恰是全过程中最陡的。

cwnd 初值按 RFC 5681 依 SMSS 分档为不超过 2~4 个 SMSS(本质是在限制初始窗口的字节数)。做题无特别说明时一律按 1 MSS。

ssthresh 有三条用法:cwnd < ssthresh 用慢开始;cwnd > ssthresh 用拥塞避免cwnd = ssthresh 时既可用慢开始也可用拥塞避免——这是标准留下的两可,做题口径见 detail 篇

拥塞避免 = 加法增大 AI:每经过一个 RTT,cwnd 加 1,线性缓慢增长。名字容易误导:"拥塞避免"并非完全避免拥塞,只是让 cwnd 增长得缓慢些,使网络不容易拥塞。

AIMD 的不对称是刻意的:越界的代价(丢包 → 重传 → 加剧拥塞)远大于保守的代价,所以逼近上限用加法、撤离用乘法;这一增一减还会把竞争同一容量的多条连接推向窗口相等——公平性即源于此

两张表就是全部规则

正常传输时:

当前阶段判定条件每经过一个 RTT,cwnd 如何变
慢开始cwnd < ssthresh翻倍(指数增长)
拥塞避免cwnd ≥ ssthresh加 1(线性增长)

发生事件时(TCP Reno)——本站关于拥塞控制动作的唯一权威口径:

事件① ssthresh 更新为② cwnd 更新为③ 随后进入
超时cwnd / 21慢开始
3 个重复确认cwnd / 2ssthresh(即 cwnd/2)拥塞避免(快恢复)

执行顺序恒为先算 ssthresh 再设 cwnd,因为 ssthresh 用的是事件发生时的(旧的)cwnd。顺序反了结果差一倍。

Tahoe 与 Reno 只差一格:只差"3 个重复确认怎么处理"——Tahoe 当超时处理(cwnd = 1、回慢开始),Reno 走快恢复(cwnd = ssthresh、进拥塞避免)。超时的处理两者完全相同,默认按 Reno。

交互可视化

加载可视化中...

四、快重传:为什么门槛是 3 个

快重传有两个动作,分属两端。接收方:不等捎带就立即发确认收到失序报文段也要立即发重复确认发送方一连收到 3 个重复确认就立即重传,不等超时。使用快重传可使整个网络吞吐量提高约 20%

门槛取 3 是两条曲线的交点:

若取会怎样
1~2 个失序也会产生重复确认。报文段走不同路由造成的乱序非常常见,只错一两个位置的乱序会立刻被误判成丢包,引发大量不必要的重传
3 个连续 3 个失序位置的乱序已经很罕见,误判概率显著下降;同时只等 3 个确认,比等一个 RTO 快得多
4 个及以上误判更少,但要等更久才能重传;等待的收益递减,而延迟的代价线性增加

3 是"误判率已经足够低"与"等待时间还足够短"的平衡点,是工程经验值而非理论最优——知道它在权衡什么就不必死记。

教材的表述是:接收方一共发出 4 个对 M2 的确认,其中后 3 个是重复确认;发送方数的是重复确认的个数

快恢复凭什么只减半而不降到 1

因为重复确认本身就是证据:接收方每收到一个失序报文段才发一个重复确认,收到 3 个说明丢包之后至少还有 3 个报文段成功穿过了网络。网络要是真堵死了,这 3 个也过不来。

"能收到重复确认"这件事本身就证明网络还通——所以只需减半,不必像超时那样退回起点。

为什么有的实现要把快恢复的 cwnd 再加 3 个 MSS(想弄清快恢复到底在恢复什么时展开)

也有的快恢复实现是把快恢复开始时的拥塞窗口 cwnd 值再增大一些(增大 3 个报文段的长度),即等于新的 ssthresh+3×MSS。这样做的理由是:既然发送方收到 3 个重复的确认,就表明有 3 个分组已经离开了网络。这 3 个分组不再消耗网络的资源而是停留在接收方的缓存中(接收方发送出 3 个重复的确认就证明了这个事实)。可见现在网络中并不是堆积了分组而是减少了 3 个分组,因此可以适当把拥塞窗口扩大些。

这条推理把"重复确认"当成了网络中在途分组数的计量工具——每收到一个重复确认,就意味着网络里少了一个分组。408 做题按 cwnd=ssthresh 即可,这个变体用于理解快恢复到底在恢复什么。

五、状态转换与 AIMD 锯齿

图里有两条容易被漏掉的边:慢开始阶段同样可能发生超时或收到 3 个重复确认。教材图 5-25 那条曲线只是特例,流程图(图 5-27)里才写全。

曲线的形状就是 AIMD 的招牌锯齿:缓慢的线性爬升(AI)+ 陡直的腰斩(MD)。它的物理含义是——TCP 在持续试探网络容量的上界:不撞到上界就永远不知道它在哪,撞到了就退回一半再慢慢爬。"拥塞控制必然伴随周期性丢包"不是缺陷,而是这套探测机制的固有代价。

教材图 5-25 那条曲线的五个拐点(想把一次完整的锯齿走一遍时展开)

初始 ssthresh = 16,cwnd 从 1 开始。这里只叙述拐点,完整的逐轮数值表在 detail 篇

拐点发生了什么之后
cwnd 由 1 指数增长到 16,达到 ssthresh改执行拥塞避免,按线性规律增长
cwnd 线性增长到 24 时出现超时第 1 次调整门限:ssthresh=24/2=12,同时 cwnd=1,执行慢开始
cwnd 重新指数增长到 12(= 新 ssthresh)改执行拥塞避免,按线性规律增大
cwnd 线性增长到 16 时,发送方一连收到 3 个重复确认判定只是丢了个别报文段,不启动慢开始
第 2 次调整门限:ssthresh=16/2=8,同时 cwnd=ssthresh=8开始执行拥塞避免算法

本节小结

  1. 拥塞的实质是系统各部分不匹配,加缓存或提速率只会把瓶颈转移;拥塞引起的重传不但不缓解拥塞,反而加剧拥塞,这条正反馈决定了所有动作必须朝"主动减少注入"去。分组丢失是拥塞的征兆而不是原因。
  2. 端系统的判据只有一条:确认有没有按时回来。 超时即"猜想"网络某处拥塞,却不知发生在何处、原因为何;前提是"因传输差错而丢弃分组的概率远小于 1%",无线链路上前提不成立,会无谓降速
  3. 四种算法的骨架:慢开始每 RTT 翻倍("慢"指起点低不指增长慢)→ 到 ssthresh 转拥塞避免每 RTT 加 1(AI)→ 事件发生时门限减半(MD),顺序恒为先算 ssthresh 再设 cwnd。超时降到 1 回慢开始;3 个重复确认只减半进快恢复,因为重复确认本身证明网络还通。Tahoe 与 Reno 只差这一格。

考点速记

拥塞控制在真题里被考过的形式只有一种:给一个起点和一个事件,问 cwnd 会变成多少、或者要多久才涨到某个值。 这一种的三道题,恰好把"超时"这个事件的前后两段各考了一遍。

① 超时之后再涨 4 个 RTT,cwnd 是多少(cn-2009-39)。MSS = 1 KB,cwnd = 16 KB 时发生超时,此后 4 个 RTT 传输都成功,问第 4 个 RTT 内发出的段全部被确认时的 cwnd。

先按顺序执行事件动作ssthresh=16/2=8cwnd=1,进入慢开始。然后逐轮走:

RTT本轮起始 cwnd阶段轮末 cwnd
11慢开始2
22慢开始4
34慢开始8(达到 ssthresh,转拥塞避免)
48拥塞避免9

C:9 KB干扰项 8 KB 是把第 4 个 RTT 也当成慢开始的终点(漏了最后那一轮的 +1),16 KB 则是完全没执行超时动作。这道题的全部难度就在第 3 到第 4 轮那个阶段切换上。

② 涨回原值最少要几个 RTT(cn-2022-38)。同样是 cwnd = 16 KB 时超时,问 cwnd 再次增长到 16 KB 至少需要多久。

同一套动作,只是改问轮数:ssthresh=8cwnd=1 之后,慢开始段 1248 用 3 个 RTT拥塞避免段 8916 每轮加 1、用 8 个 RTT,合计 11 RTT,答 C

四个选项 4/5/11/16 覆盖四种算法:答 4 的是全程按慢开始(116 只要 4 轮);答 16 的是全程按拥塞避免;答 5 的多半是把慢开始段数成 4 轮又漏算了后半段。必须把两段分开数,而且分界点在 cwnd = ssthresh = 8 那一刻。

③ 问"最长"时间怎么算(cn-2020-38)。MSS = 1 KB、RTT = 2 ms,问在不出现拥塞的前提下,cwnd 从 8 KB 增长到 32 KB 所需的最长时间。

"最长"这个词是这道题唯一的机关。 同样从 8 涨到 32,走慢开始只要 2 个 RTT(81632),走拥塞避免要 24 个 RTT(每轮 +1)。问最长,就取全程拥塞避免24×2=48 ms,答 D

选项 A(4 ms)正是"全程慢开始"的答案——如果题目问的是"最短",它就对了。看到"最长/最短"先想清楚该套哪条增长规律,这比算数重要得多。

本篇练习区里还会出现四道题,它们都要同时跟踪 cwnd 与 rwnd 两条线,讲在拥塞控制典型计算题TCP 流量控制:cn-2014-38、cn-2017-39、cn-2025-38 在前者,cn-2015-39 在后者。

本篇的吞吐量-负载曲线、快重传门槛为什么是 3、快恢复为什么只减半——在真题里不单独成题,但它们支撑着上面三道题里的每一个动作:知道"超时是强信号、3 个重复确认是弱信号",才不会把两种事件的处置搞混;知道 AIMD 的不对称是刻意的,才明白为什么减用除法、增用加法。

易错顺序恒为先算 ssthresh(用旧 cwnd 的一半)再设 cwnd。 反了结果差一倍。

易错超时后 cwnd 降到 1、回慢开始;3 个重复确认只降到 ssthresh、进拥塞避免。 两种事件处置不同。

易错慢开始与拥塞避免要分段数轮数,分界点是 cwnd 达到 ssthresh 那一刻。

易错问"最长时间"取拥塞避免、问"最短时间"取慢开始。 这个词决定套哪条规律。

易错"慢开始"的慢指起点低,不指增长慢,它的斜率是全过程最陡的。

易错"拥塞避免"并非完全避免拥塞,只是让 cwnd 涨得慢些。

易错cwnd = ssthresh 时标准两可,408 真题按"达到即转拥塞避免"处理。

易错发送窗口是 min(cwnd,rwnd),题面给了接收缓存就一定要把 rwnd 那条线也跟上。

教材出处
  • 谢希仁《计算机网络》(第 8 版)p238(5.8.1 拥塞控制的一般原理):拥塞的定义式 (5-7) 与"在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫作拥塞";否掉"加资源"的两段推理——"现在设想将该节点缓存的容量扩展到非常大……由于输出链路的容量和处理机的处理速度并未提高,因此在这队列中的绝大多数分组的排队等待时间将会大大增加,结果上层软件只好把它们进行重传"、"处理机处理的速率太低可能引起网络的拥塞。简单地将处理机的速率提高,可能会使上述情况缓解一些,但往往又会将瓶颈转移到其他地方。问题的实质往往是整个系统的各个部分不匹配。只有所有的部分都平衡了,问题才会得到解决";以及正反馈——"拥塞引起的重传并不会缓解网络的拥塞,反而会加剧网络的拥塞";还有拥塞控制与流量控制的定性——"拥塞控制是一个全局性的过程,涉及所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。但 TCP 连接的端点只要迟迟不能收到对方的确认信息,就猜想在当前网络中的某处很可能发生了拥塞,但这时却无法知道拥塞到底发生在网络的何处,也无法知道发生拥塞的具体原因"、"流量控制往往是指点对点通信量的控制,是个端到端的问题(接收端控制发送端)"。
  • 同书 p239–p240:图 5-23 的三阶段解读——"具有理想拥塞控制的网络,在吞吐量饱和之前,网络吞吐量应等于提供的负载,故吞吐量曲线是 45° 的斜线"、"当网络的吞吐量明显地小于理想的吞吐量时,网络就进入了轻度拥塞的状态"、"当提供的负载达到某一数值时,网络的吞吐量反而随提供的负载的增大而下降,这时网络就进入了拥塞状态"、"网络的吞吐量就下降到零,网络已无法工作,这就是所谓的死锁";以及"分组的丢失是网络发生拥塞的征兆而不是原因"、"在许多情况下,甚至正是拥塞控制机制本身成为引起网络性能恶化甚至发生死锁的原因"。
  • 同书 p241(5.8.2 TCP 的拥塞控制方法):cwnd 的定义与控制原则——"发送方维持一个叫作拥塞窗口 cwnd 的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且是动态变化着的";判据与其前提——"只要发送方没有按时收到对方的确认报文,也就是说,只要出现了超时,就可以估计可能在网络某处出现了拥塞。现在通信线路的传输质量一般都很好,因传输出差错而丢弃分组的概率是很小的(远小于 1%)";慢开始的思路"当主机在已建立的 TCP 连接上开始发送数据时,并不清楚网络当前的负荷情况……较好的方法是先探测一下,即由小到大逐渐增大注入到网络中的数据字节";以及初始 cwnd 按 SMSS 分档的三条规定(RFC 5681)。
  • 同书 p242:式 (5-8) "拥塞窗口 cwnd 每次的增加量 = min(N, SMSS)"及其中 N 的含义;"发送方并不是要在所有的确认都收齐了之后才调整其拥塞窗口,而是收到一个确认就调整一下拥塞窗口";"慢开始的'慢'并不是指 cwnd 的增长速率慢,而是指在 TCP 开始发送报文段时,只发送一个报文段,即设置 cwnd=1,目的是试探一下网络的拥塞情况"
  • 同书 p243:ssthresh 的三条用法(cwnd < ssthresh 用慢开始、cwnd > ssthresh 用拥塞避免、cwnd = ssthresh 时既可使用慢开始算法,也可使用拥塞避免算法);拥塞避免"每经过一个往返时间 RTT,发送方的拥塞窗口 cwnd 的大小就加 1……因此在拥塞避免阶段就称为'加法增大'AI";"'拥塞避免'并非完全避免拥塞,而是让拥塞窗口增长得缓慢些,使网络不容易出现拥塞";以及图 5-25 五个拐点的完整叙述(ssthresh 初值 16、cwnd=24 时超时、第 1 次调整 ssthresh=12、cwnd=16 时收到 3-ACK、第 2 次调整 ssthresh=8 且 cwnd=8)。
  • 同书 p244:快重传算法的完整描述——"接收方必须立即发送对 M2 的重复确认,以便让发送方及早知道接收方没有收到报文段 M3……快重传算法规定,发送方只要一连收到 3 个重复确认,就可知道现在并未出现网络拥塞,而只是接收方少收到一个报文段,因而立即进行重传 M3(即'快重传')使用快重传可以使整个网络的吞吐量提高约 20%";快恢复的三步与 AIMD 的定义"一旦出现超时或 3 个重复的确认,就要把门限值设置为当前拥塞窗口值的一半,并大大减小拥塞窗口的数值。这常称为'乘法减小'MD……二者合在一起就是所谓的 AIMD 算法";以及 ssthresh+3×MSS 那个变体的完整理由——"既然发送方收到 3 个重复的确认,就表明有 3 个分组已经离开了网络。这 3 个分组不再消耗网络的资源而是停留在接收方的缓存中……可见现在网络中并不是堆积了分组而是减少了 3 个分组"。此页还说明图 5-25 只是特例,慢开始阶段出现超时或 3-ACK 的处理要看图 5-27 的流程图。
  • 同书 p245:式 (5-9) 与判读——"发送方窗口的上限值 = Min[rwnd, cwnd]……当 rwnd < cwnd 时,是接收方的接收能力限制发送方窗口的最大值。反之,当 cwnd < rwnd 时,则是网络的拥塞程度限制发送方窗口的最大值"。
  • 同书 p245(5.8.3 主动队列管理 AQM):路由器分组丢弃策略对 TCP 拥塞控制的影响,本篇只作指路,展开见 网络层功能

相关知识

TCP 拥塞控制典型计算题TCP 流量控制网络层功能与拥塞控制

真题练习