从滑动窗口到拥塞控制:TCP高效可靠传输的三大支柱

目录

一、流量控制:"接收方驱动"的速率调节机制

1、什么是流量控制?

2、为什么需要流量控制?

3、流量控制如何工作?------窗口机制

[1. 窗口大小字段的作用](#1. 窗口大小字段的作用)

窗口变化

[2. 窗口为 0 时的处理:窗口探测(Window Probe)](#2. 窗口为 0 时的处理:窗口探测(Window Probe))

4、关于窗口大小的限制与扩展

[1. 基础窗口大小的限制](#1. 基础窗口大小的限制)

[2. 窗口缩放选项(Window Scaling Option)](#2. 窗口缩放选项(Window Scaling Option))

5、初始窗口大小如何确定?

[6、流量控制 vs 拥塞控制](#6、流量控制 vs 拥塞控制)

7、流量控制总结

[二、滑动窗口机制:TCP 高效可靠传输的核心](#二、滑动窗口机制:TCP 高效可靠传输的核心)

1、引言:为什么需要滑动窗口?

2、滑动窗口的基本概念

发送缓冲区的三部分划分

3、滑动窗口的工作原理

[1. 窗口大小的决定因素](#1. 窗口大小的决定因素)

窗口变化

[2. 滑动过程示例](#2. 滑动过程示例)

总结归纳

4、滑动窗口的动态性:不一定是"整体右移"

示例:接收方处理变慢

5、滑动窗口的实现模型

6、滑动窗口与重传机制

丢包的两种典型场景

[情况一:ACK 丢失(数据已到达)](#情况一:ACK 丢失(数据已到达))

[情况二:数据包丢失(如 A 段丢失)](#情况二:数据包丢失(如 A 段丢失))

7、重要澄清:滑动窗口内的数据是否都未被接收?

[8、快重传 vs 超时重传](#8、快重传 vs 超时重传)

9、总结:滑动窗口的核心价值

[三、TCP 拥塞控制详解:防止网络"雪崩"的智能调节机制](#三、TCP 拥塞控制详解:防止网络“雪崩”的智能调节机制)

1、为什么需要拥塞控制?

[流量控制 vs 拥塞控制](#流量控制 vs 拥塞控制)

2、拥塞控制的核心思想

3、拥塞窗口(cwnd)与实际发送窗口

4、拥塞控制的四大核心算法

[1. 慢启动(Slow Start)](#1. 慢启动(Slow Start))

[2. 拥塞避免(Congestion Avoidance)](#2. 拥塞避免(Congestion Avoidance))

[3. 快速重传与快速恢复(Fast Retransmit & Fast Recovery)](#3. 快速重传与快速恢复(Fast Retransmit & Fast Recovery))

[4. 超时重传(Timeout) → 重回慢启动](#4. 超时重传(Timeout) → 重回慢启动)

5、拥塞控制全过程图解(经典模型)

6、关键细节补充

[1. 初始 ssthresh 的设置](#1. 初始 ssthresh 的设置)

[2. 拥塞信号的判断](#2. 拥塞信号的判断)

[3. 所有 TCP 主机协同工作](#3. 所有 TCP 主机协同工作)

[4. cwnd 与 rwnd 的动态博弈](#4. cwnd 与 rwnd 的动态博弈)

7、现代拥塞控制算法的发展

8、总结:拥塞控制的意义


一、流量控制:"接收方驱动"的速率调节机制

1、什么是流量控制?

接收端处理数据的能力是有限的。如果发送端传输速度过快,导致接收端缓冲区溢出,此时若发送端仍持续发送数据,将引发丢包问题,进而触发一系列连锁反应,如丢包重传等。为此,TCP协议支持根据接收端的处理能力动态调整发送端的传输速率,这一机制称为流量控制(Flow Control)。

流量控制(Flow Control) 是 TCP 协议中用于协调发送端与接收端之间数据传输速率的重要机制。其核心目标是:

防止发送端发送数据的速度超过接收端的处理能力,从而避免接收缓冲区溢出、数据丢失以及由此引发的重传和网络拥塞等问题。

简单来说,流量控制是一种"接收方驱动"的速率调节机制,确保发送方不会"压垮"接收方。

  • 接收端通过TCP首部中的"窗口大小"字段告知发送端其当前可用的缓冲区空间大小;

  • 窗口大小值越大,表明网络吞吐量越高;

  • 当接收端缓冲区接近满载时,会主动减小窗口大小值通知发送端;

  • 发送端根据接收到的窗口大小调整数据发送速率;

  • 若接收端缓冲区完全饱和,则将窗口置零,此时发送方暂停数据传输,但需定期发送窗口探测报文以获取最新的窗口大小信息。

接收端如何告知发送端窗口大小呢?实际上,TCP首部中的16位窗口字段就用于存储窗口大小信息。不过16位数字最大只能表示65535,这是否意味着TCP窗口最大只能是65535字节呢?并非如此。TCP首部40字节选项中还包含一个窗口扩大因子M,实际窗口大小等于窗口字段值左移M位后的结果。

2、为什么需要流量控制?

  • **接收端处理能力有限:**接收端的内核为每个 TCP 连接分配了固定大小的接收缓冲区(Receive Buffer)。如果上层应用程序读取数据的速度较慢,而发送端持续高速发送,缓冲区很快会被填满。

  • **缓冲区溢出导致丢包:**一旦接收缓冲区满,新到达的数据包将被丢弃。TCP 的可靠性机制会触发重传,不仅浪费带宽,还可能加剧网络拥塞。

  • **系统资源保护:**流量控制有助于维持系统稳定性,避免因内存耗尽或处理过载导致服务崩溃。

3、流量控制如何工作?------窗口机制

TCP 使用 滑动窗口(Sliding Window) 机制实现流量控制,其关键字段是 TCP 首部中的 "窗口大小(Window Size)" 字段。

1. 窗口大小字段的作用

  • 接收端在发送 ACK 报文 时,会在 TCP 头部的 窗口大小字段 中填入当前 还能接收多少字节的数据(即剩余缓冲区空间)。

  • 发送端根据该值动态调整自己的发送速率:不能发送超过窗口大小的数据量

窗口变化
  • 窗口越大 → 接收能力越强 → 发送端可发得更快

  • 窗口变小 → 接收能力下降 → 发送端需减速

  • 窗口为 0 → 暂停发送 → 等待接收端恢复

2. 窗口为 0 时的处理:窗口探测(Window Probe)

当接收端缓冲区满,窗口大小设为 0,发送端必须停止发送有效数据。但不能永远等待,因此采用 主动探测机制

  • 发送端定期发送"窗口探测报文"(仅含 TCP 头,无应用数据)。

  • 接收端收到后,即使窗口仍为 0,也必须回复一个 ACK 并携带当前窗口大小。

  • 一旦接收端上层应用读走部分数据,缓冲区有空闲,就会在下一个 ACK 中通告一个非零窗口,发送端即可恢复传输。

**这种机制避免了"死锁":**若接收端因窗口为 0 而不再发送任何报文,发送端将永远不知道何时能继续发送。

4、关于窗口大小的限制与扩展

1. 基础窗口大小的限制

  • TCP 首部中"窗口大小"字段为 16 位 ,最大值为 65,535 字节(约 64KB)

  • 在早期低速网络中足够使用,但在现代高速网络(如千兆、万兆以太网)中,64KB 窗口会严重限制吞吐量(受 带宽 × 时延积 限制)。

2. 窗口缩放选项(Window Scaling Option)

为突破 65KB 限制,RFC 1323 引入了 窗口扩大因子(Window Scale Factor)

  • TCP 三次握手阶段 ,双方通过 TCP 选项字段 协商一个缩放因子 M(0 ≤ M ≤ 14)

  • 实际窗口大小 = 窗口字段值 × 2^M(等价于左移 M 位)。

  • 例如:若窗口字段为 65535,M=3,则实际窗口 = 65535 × 8 = 524,280 字节(约 512KB)

  • 最大理论窗口可达 65535 × 2^14 ≈ 1GB,足以支持高速长距离网络。

**注意:**窗口缩放仅在 SYN 报文中协商,连接建立后不可更改。

5、初始窗口大小如何确定?

在正式传输数据前,双方已通过 TCP 三次握手 交换了初始接收能力:

  1. 客户端发送 SYN:携带自己的初始窗口大小(如 65535)及窗口缩放因子(如 WS=7)。

  2. 服务器回复 SYN-ACK:同样携带自己的初始窗口和缩放因子。

  3. 客户端发送 ACK:完成握手,双方已知对方的初始接收窗口。

因此,第一次发送数据时,发送端已经知道接收端的窗口大小,不会盲目发送导致溢出。

6、流量控制 vs 拥塞控制

特性 流量控制(Flow Control) 拥塞控制(Congestion Control)
目标 保护接收端不被压垮 保护网络不发生拥塞
驱动方 接收端(通过窗口通告) 发送端(基于丢包/RTT等网络反馈)
依据 接收缓冲区剩余空间 网络链路状态(如丢包率、延迟)
机制 滑动窗口 + 窗口通告 慢启动、拥塞避免、快重传、快恢复等

两者协同工作:流量控制管"点对点",拥塞控制管"端到端网络"

7、流量控制总结

  • 流量控制是 TCP 可靠传输的关键保障之一,通过接收端动态通告窗口大小,使发送端自适应调整发送速率。

  • 窗口为 0 时通过窗口探测机制避免死锁

  • 窗口缩放机制突破了 64KB 限制,适应现代高速网络。

  • 初始窗口在三次握手中协商完成,确保通信开始即安全。

  • 流量控制与拥塞控制相辅相成,共同维护网络稳定与高效。

通过以上机制,TCP 在保证数据可靠传输的同时,实现了对发送速率的智能调控,是其成为互联网核心传输协议的重要原因之一。


二、滑动窗口机制:TCP 高效可靠传输的核心

1、引言:为什么需要滑动窗口?

在早期的简单确认机制(Stop-and-Wait)中,发送方每发送一个数据段后必须等待接收方的 ACK 确认,才能发送下一个数据段。这种方式虽然可靠,但效率极低------网络带宽大部分时间被空闲等待浪费 。为提升吞吐效率,TCP 引入了 滑动窗口(Sliding Window) 机制,允许发送方 连续发送多个数据段而无需逐个等待 ACK,从而将"发送"与"等待"过程重叠,显著提高链路利用率,提高速度。

核心思想 :"不必等一个包的确认,就发下一包;只要不超过对方能接收的总量,就可以持续发送。"

2、滑动窗口的基本概念

窗口大小指的是无需等待确认应答即可继续发送数据的最大上限。如图所示,当前窗口大小为4000字节(对应四个数据段)。

具体工作原理如下:

  • 发送端可以连续发送前四个数据段,无需等待任何ACK确认;

  • 当收到第一个ACK确认后,窗口向后滑动,允许发送第五个数据段;

  • 操作系统内核通过维护发送缓冲区来跟踪未确认的数据,只有收到确认的数据才会从缓冲区移除;

  • 窗口大小直接影响网络吞吐量,窗口越大,网络吞吐率越高。

发送缓冲区的三部分划分

在 TCP 发送端的缓冲区中,数据按状态可分为三类:

区域 状态 说明
已确认(ACKed) 已发送且已收到 ACK 可安全释放或覆盖
已发送未确认(Unacked) 已发送但未收到 ACK 必须保留,用于可能的重传
未发送(Not Sent) 尚未发送 等待窗口滑动后发送

滑动窗口(Sliding Window)通常指"已发送未确认 + 可发送但尚未发送"的整个可操作区域

窗口大小(Window Size) = 接收方通告的窗口值(受流量控制限制),表示当前最多可发送多少字节而无需等待 ACK。

有些资料将"已发送未确认"部分单独称为"窗口",而将整个可发送范围称为"滑动窗口"。两种说法均存在,但本质一致。

3、滑动窗口的工作原理

1. 窗口大小的决定因素

滑动窗口的实际大小由两个因素共同决定:有效窗口大小 = min(接收方通告窗口,拥塞窗口)

  • 滑动窗口的大小等于对方窗口大小与自身拥塞窗口大小的较小值,因为发送数据时不仅要考虑对方的接收能力,还要考虑当前网络的状况。

  • 接收方窗口(rwnd) :由接收端通过 ACK 报文中的"窗口字段"告知,反映其缓冲区剩余空间(流量控制)。

  • 拥塞窗口(cwnd) :由发送端根据网络状况动态调整(拥塞控制)。

本节先聚焦流量控制视角,假设拥塞窗口足够大,窗口大小 = 接收方窗口。

窗口变化
  • 窗口越大 → 接收能力越强 → 发送端可发得更快

  • 窗口变小 → 接收能力下降 → 发送端需减速

  • 窗口为 0 → 暂停发送 → 等待接收端恢复

2. 滑动过程示例

假设:

  • 初始序列号从 1001 开始

  • 接收方窗口大小固定为 4000 字节(即 4 个 1000 字节的数据段)

步骤如下

  1. 初始状态:发送方可一次性发送 4 段数据:1001--2000、2001--3000、3001--4000、4001--5000(共 4000 字节,填满窗口)

  2. 接收方收到 ACK=2001 :表示 1001--2000 已被接收。然后接收方执行下面的操作:

    • 将该段移入"已确认"区域。

    • 窗口左边界右移至 2001。

    • 若接收方窗口仍为 4000,则右边界变为 2001 + 4000 = 6001。

    • 此时可发送新段:5001--6000。

  3. 窗口持续"滑动":随着 ACK 到达,窗口不断右移,实现流水线式发送。

总结归纳
  • 滑动窗口的本质是"动态维护一个可发送的字节区间",通过左右边界的移动实现高效传输。

  • 当发送方陆续收到数据段对应的ACK确认时,可将已确认的数据段移至滑动窗口左侧。此时系统会根据当前窗口大小决定是否将右侧待发送数据纳入窗口范围。

  • TCP重传机制要求保留已发送但未确认的数据,这些数据恰好位于滑动窗口内。只有窗口左侧已被确认接收的数据才能被覆盖或删除,因为这些数据已确保可靠送达。

  • 因此,滑动窗口不仅限制了无需等待ACK即可发送的数据量,同时也为TCP重传机制提供了支持。

4、滑动窗口的动态性:不一定是"整体右移"

滑动窗口的大小和位置 并非固定不变,而是随接收方处理能力动态调整。

示例:接收方处理变慢

  • 发送方已发送 1001--5000(4 段),窗口大小为 4000。

  • 接收方收到 1001--2000 后,上层应用未及时读取缓冲区,导致剩余空间减少。

  • 接收方在 ACK=2001 中将窗口大小更新为 3000

此时:

  • 窗口左边界移至 2001。

  • 窗口右边界 = 2001 + 3000 = 5001。

  • 无法发送 5001--6000,因为窗口已缩小!

结论 :滑动窗口可能 变窄、变宽、甚至暂时停止滑动,完全取决于接收方的实时窗口通告。

5、滑动窗口的实现模型

TCP的接收和发送缓冲区可以视为字符数组,滑动窗口则是由两个指针界定的区间范围。其中,start指针标记窗口左边界,end指针标记窗口右边界,两者之间的区域即为滑动窗口。

当发送端收到接收方的响应时,若响应中的确认序号为x,窗口大小为win,发送端会执行以下操作:将start指针更新为x,并将end指针更新为start + win。

从编程角度看,滑动窗口可抽象为 两个指针(或序号)界定的区间

  • left(start):已确认的下一个字节序号(即最新 ACK 值)

  • right(end):left + 当前窗口大小

每当收到 ACK:

  • 更新 left = ACK_seq

  • 根据新窗口大小更新 right = left + window_size

此模型简洁高效,广泛用于 TCP 协议栈实现。

6、滑动窗口与重传机制

滑动窗口不仅提升效率,还 天然支持 TCP 的可靠重传机制

  • 窗口内数据必须保留:因为尚未确认,可能需要重传。

  • 窗口左侧数据可释放:已确认,无需再保存。

丢包的两种典型场景

情况一:ACK 丢失(数据已到达)
  • 发送方连续发送 A、B、C、D 四段。

  • B 和 D 的 ACK 丢失,但 C 的 ACK 到达,且确认序号为 D 之后(如 6001)。

  • TCP 的累积确认机制:ACK=6001 表示"1--6000 全部收到",因此 A、B、C、D 均视为已确认。

  • 无需重传,ACK 丢失不影响正确性。

在连续发送多个数据报文时,部分ACK丢失并不会影响通信可靠性,因为后续到达的ACK可以完成确认工作。

以图示为例,假设2001-3000和4001-5000数据包对应的ACK丢失。但只要发送端收到5001-6000数据包的ACK响应,就能确认之前两个数据包已被接收。这是因为接收方会在ACK中设置确认序号为6001,表明1-6000范围内的所有数据均已接收完成,并指示发送方应从6001序号继续发送数据。

情况二:数据包丢失(如 A 段丢失)
  • 接收方收到 B、C、D,但缺少 A。

  • 接收方只能重复发送 ACK=1001(期望下一段从 1001 开始)。

  • 发送方若连续收到 3 次相同 ACK(DupACK) ,立即触发 快重传(Fast Retransmit),重发 A 段。

  • 接收方收到 A 后,可一次性确认到 D(ACK=6001)。

快重传优势:无需等待超时(可能数百毫秒),通常在几毫秒内完成重传。

如上图,当1001-2000的数据包丢失时,发送端会持续收到确认序号为1001的响应报文,这实际上是在提示发送端"需要从序号1001开始重新发送数据",相当于接收端在明确告知发送端:"我需要1001号报文"。

如果发送端连续收到三个确认序号为1001的响应报文,就会立即重传1001-2000的数据包。当接收端成功接收该数据包后,会直接发送确认序号为6001的响应报文,因为2001-6000的数据已经在之前被成功完整接收,并存储在操作系统内核的接收缓冲区中。这种高效的丢包重传机制被称为"快速重传"(Fast Retransmit)。

需要特别说明的是,快重传机制需要在批量重传和选择性重传之间取得平衡。在本例中,发送端无法确定具体丢失的是1001-2000这个数据包。理论上,当收到重复的1001确认时,发送端应该重传1001-7000的所有数据,但这可能导致大量数据重复传输。因此,更合理的做法是先重传1001-2000的数据包,然后根据后续收到的确认序号来决定是否需要重传其他数据包。

7、重要澄清:滑动窗口内的数据是否都未被接收?

不一定! 滑动窗口内的数据只是"尚未被确认 ",但可能已被接收方收到,只是因为前面有缺失数据,无法推进确认序号。

滑动窗口中的数据是指那些暂时无需对方确认的数据,而非表示这些数据都未被接收。实际上,窗口内部分数据可能已被对方成功接收,但由于靠近窗口左侧的数据在传输中丢失(如丢包),导致后续已接收的数据无法得到确认响应。

举例:

  • 发送:1001--2000(丢失)、2001--3000(收到)、3001--4000(收到)

  • 接收方只能回复 ACK=1001

  • 此时 2001--4000 虽在接收缓冲区,但仍在发送方的滑动窗口内(未确认)

  • 一旦重传 1001--2000 成功,接收方立即 ACK=4001,窗口瞬间滑动

这体现了 TCP 按序交付累积确认 的特性。

如下图,假设数据包1001-2000在传输过程中丢失,即使2001-5000的数据已被接收,对方返回的确认序号仍只能是1001。当发送方重传1001-2000的数据包后,接收方确认序号将更新为5001,此时发送缓冲区中1001-5000的数据会立即移动到滑动窗口的左侧。

8、快重传 vs 超时重传

快速重传机制能够实现数据的即时重发。当发送端连续收到三次相同的应答时,该机制就会被触发。与超时重传不同,它无需依赖重传定时器,也不需要在固定时间后才执行重传。尽管快速重传能迅速判断数据包丢失,但它并不能完全取代超时重传。在某些情况下,数据包丢失后可能无法收到对方的三次重复应答,此时快速重传机制就无法启动,只能依靠超时重传。因此,虽然快速重传提高了传输效率,但超时重传作为所有重传机制的基础保障,仍然是不可或缺的。

特性 快重传(Fast Retransmit) 超时重传(Timeout Retransmit)
触发条件 连续收到 3 个重复 ACK 重传定时器超时(RTO)
响应速度 极快(通常 < RTT) 较慢(RTO ≥ RTT,常为数百 ms)
适用场景 单个或少量包丢失 大量丢包、网络中断、ACK 完全丢失
是否必需 优化机制 保底机制,不可或缺

快重传不能替代超时重传!例如:若第一个数据包丢失,且后续无数据发送,则不会产生 DupACK,只能依赖超时重传。

9、总结:滑动窗口的核心价值

  • 提升吞吐效率:允许多包并发发送,避免 Stop-and-Wait 的低效。

  • 实现流量控制:窗口大小由接收方动态控制,防止缓冲区溢出。

  • 支持可靠传输:保留未确认数据,配合重传机制保证可靠性。

  • 适应动态网络:窗口可伸缩,响应接收能力与网络状态变化。

  • 与拥塞控制协同:实际窗口受 rwnd 和 cwnd 共同约束,兼顾端到端与网络整体健康。

滑动窗口是 TCP 实现"高吞吐 + 高可靠"平衡的关键设计,也是现代互联网高效通信的基石之一。


三、TCP 拥塞控制详解:防止网络"雪崩"的智能调节机制

1、为什么需要拥塞控制?

在 TCP 通信中,少量丢包是正常的 ,可通过快重传或超时重传来恢复。但当大量丢包集中发生 时,问题的性质就发生了根本变化------这不再是端到端的个别故障,而是整个网络路径出现了拥塞(Congestion)

网络拥塞的本质:当多个主机同时向网络注入大量数据,导致路由器缓冲区溢出、排队延迟剧增、甚至丢包,形成"恶性循环"------越丢包越重传,越重传越拥塞。

流量控制 vs 拥塞控制

机制 目标 控制依据 作用范围
流量控制(Flow Control) 防止接收方缓冲区溢出 接收方通告的窗口大小(rwnd) 点对点(发送端 ↔ 接收端)
拥塞控制(Congestion Control) 防止网络过载 网络反馈(丢包、延迟等) 端到端(整个通信路径)

关键区别

  • 流量控制问:"对方能收多少?"

  • 拥塞控制问:"网络能承受多少?"

TCP 必须同时考虑两者,才能实现高效且不破坏网络稳定性的传输。

  • **流量控制:**基于接收方的缓冲能力来调节发送速率,防止缓冲区溢出导致数据丢失。

  • **滑动窗口:**允许发送方在未收到确认的情况下连续发送多个数据包,从而提升传输效率。

  • **拥塞控制:**监测网络状况动态调整发送速率,当超过网络承载能力时主动降低传输速度以避免拥塞恶化。

TCP协议对偶发的少量丢包具有容忍性,但当丢包率超过临界值时,系统会自动判定网络出现拥塞,此时将优先采取拥塞控制措施而非继续推测收发双方的问题。

2、拥塞控制的核心思想

在网络出现大面积瘫痪时,通信双方作为网络中的两台普通主机,看似无能为力。"雪崩时,没有一片雪花是无辜的。 ",网络故障往往是网络中大量主机共同作用的结果。虽然单个主机无法直接修复网络拥塞,但所有 TCP 主机若能协同减速,就能避免"集体踩油门"导致的系统性崩溃。

当网络中的主机同时大量发送数据时,关键节点的路由器会堆积大量报文,导致报文无法在规定时间内到达目标主机,从而引发丢包问题。面对网络拥塞,通信双方虽无法直接解决问题,但至少可以避免加重网络负担。

因此,TCP 拥塞控制的基本策略是:

在出现大量丢包时,主机不应立即重传报文,而应减少或暂停数据发送,待网络状况改善后再逐步恢复传输速率。值得注意的是,网络拥塞影响的是网络中几乎所有主机,所有使用TCP协议的主机都会执行拥塞避免算法。

  1. 探测网络容量:初始阶段谨慎发送,逐步试探。

  2. 快速响应拥塞信号:一旦检测到拥塞(如丢包),立即大幅降低发送速率。

  3. 缓慢恢复:在确认网络恢复后,再逐步提升速率。

这一策略通过 拥塞窗口(Congestion Window, cwnd) 实现。因此,拥塞控制看似是单台主机的通信策略,实则是全网主机在网络崩溃时共同遵守的规则。一旦发生拥塞,所有受影响主机都会执行拥塞避免,从而有效缓解网络压力。这种协同机制既能预防"雪崩"发生,也能在故障出现后加速网络恢复。

3、拥塞窗口(cwnd)与实际发送窗口

TCP 发送方在决定一次能发多少数据时,需同时考虑两个限制:实际发送窗口 = min(接收方窗口rwnd,拥塞窗口cwnd)

  • rwnd:由接收方通过 ACK 报文告知,体现其缓冲区能力(流量控制)。

  • cwnd:由发送方根据网络状况动态调整,体现网络承载能力(拥塞控制)。

初始时,cwnd 很小;随着网络表现良好,cwnd 增大;一旦出现拥塞,cwnd 急剧缩小。

4、拥塞控制的四大核心算法

现代 TCP 拥塞控制主要由以下四个阶段/机制组成:

1. 慢启动(Slow Start)

滑动窗口机制虽然能高效可靠地传输大量数据,但如果在初始阶段就发送大量数据,可能会引发网络问题。由于网络中连接着众多计算机,当前网络可能已处于拥塞状态。若在不了解网络状况的情况下贸然发送大量数据,很可能加剧网络拥塞。

为此,TCP引入了慢启动机制:在通信初期先发送少量数据探测网络状况,待确认当前网络拥堵程度后,再确定合适的数据传输速率。

**注意:**名字具有误导性------"慢启动"其实增长非常快!!!

目的:在连接初期快速探测网络可用带宽。

规则

  • 初始 cwnd = 1 MSS(Maximum Segment Size,通常 1460 字节)

  • 每收到一个 ACK,cwnd += 1 MSS ;即:每轮 RTT 内,cwnd 翻倍(指数增长)

示例(单位:MSS):

RTT 轮次 发送数据量 收到 ACK 数 cwnd 更新
0 1 1 cwnd = 2
1 2 2 cwnd = 4
2 4 4 cwnd = 8
3 8 8 cwnd = 16

注意:指数增长虽快,但若无限制,极易再次引发拥塞。

2. 拥塞避免(Congestion Avoidance)

触发条件 :cwnd ≥ 慢启动阈值(ssthresh)

目的 :在接近网络容量时,线性增长,避免激进扩张。

规则

  • 每收到一个 ACK,cwnd += \frac{1}{\text{cwnd}} MSS

  • 效果:每 RTT 增加 1 MSS(线性增长)

从"指数爆炸"转为"稳步爬升",更安全地逼近网络极限。

3. 快速重传与快速恢复(Fast Retransmit & Fast Recovery)

触发条件 :收到 3 个重复 ACK(DupACK)

含义:中间某个包丢失,但后续包已到达(说明网络并未完全瘫痪)。

操作

  1. 立即重传丢失的数据段(快重传)

  2. 将 ssthresh 设为当前 cwnd 的一半

  3. 进入"快速恢复"状态

    • cwnd = ssthresh + 3(补偿已收到的 DupACK)

    • 每收到一个 DupACK,cwnd += 1

    • 收到新 ACK 后,退出快速恢复,进入拥塞避免

优势:避免回到慢启动(cwnd=1),保留部分已探知的带宽。

4. 超时重传(Timeout) → 重回慢启动

触发条件:重传定时器超时(RTO)

含义:网络可能严重拥塞,甚至通信中断。

操作

  1. ssthresh = cwnd / 2

  2. cwnd = 1 MSS

  3. 重新进入慢启动阶段

注意: 这是最"保守"的响应,因为超时意味着长时间无有效反馈,网络状况极差。

具体过程如下:

当主机A向主机B发送数据时,可能因网络拥堵导致数据无法送达。此时,若主机A在设定时间内未收到B的确认应答,便会触发数据重传机制。但需注意的是,未收到应答也可能是由于B发出的ACK报文在传输过程中丢失所致。

主机B可能会收到大量重复数据。TCP协议需要能够识别并丢弃这些重复的数据包。

我们可以利用前面提到的序列号机制来轻松实现去重功能。那么,如何确定合适的超时时间呢?

理想情况下,我们需要找到一个最小时间值,确保"确认应答一定能在该时间内返回"。但这个时间长度会因网络环境的不同而变化。

  • 如果超时时间设置过长,会影响整体的重传效率;

  • 如果设置过短,则可能导致频繁发送重复数据包。

为了保证在各种网络环境下都能实现高性能通信,TCP会动态计算最大超时时间。在Linux系统(以及BSD Unix和Windows)中:

  1. 超时时间以500ms为单位进行控制,每次重传的超时时间都是500ms的整数倍;

  2. 首次重传后若无应答,等待2×500ms后再次重传;

  3. 若仍无应答,则等待4×500ms重传,以此类推,按指数级递增;

  4. 当重传次数达到上限时,TCP会认为网络或对端主机出现异常,强制关闭连接。

5、拥塞控制全过程图解(经典模型)

TCP除了具备窗口大小和滑动窗口机制外,还引入了拥塞窗口的概念。拥塞窗口是一个防止网络过载的关键阈值,当发送数据量超过该窗口大小时,就可能引发网络拥塞。

  • 在初始阶段,拥塞窗口默认设置为1。每当发送方收到一个ACK确认时,拥塞窗口值就会递增1。

  • 在实际数据传输过程中,发送方会比较拥塞窗口与接收端反馈的窗口大小,并选取两者中的较小值作为滑动窗口的实际尺寸。

每收到一个ACK应答,拥塞窗口值就增加1,此时窗口呈指数级增长。在不考虑接收方处理能力的情况下,滑动窗口的大小完全由拥塞窗口决定。其增长过程如下:

拥塞窗口 滑动窗口
1=2^0 1
1+1=2=2^1 2
2+2=4=2^2 4
4+4=8=2^3 8
... ...

然而,指数级增长的速度实际上非常迅猛。所谓"慢启动"只是在初始阶段相对缓慢,随着时间推移增长速度会越来越快。如果拥塞窗口持续以指数方式增长,很可能在短时间内再次引发网络拥塞问题。

为防止这种情况发生,系统不会让拥塞窗口始终保持指数增长。为此引入了慢启动阈值机制:当拥塞窗口超过该阈值时,增长方式就从指数增长转变为线性增长。

在TCP连接初始阶段,慢启动阈值被设置为对方窗口的最大值。每当发生超时重传时,慢启动阈值会调整为当前拥塞窗口的一半,同时将拥塞窗口重置为1,如此循环往复。

这里引入一个名为慢启动阈值的概念:当拥塞窗口超过该阈值时,其增长方式将从指数增长转变为线性增长。

假设初始 ssthresh = 16 MSS:

图示说明:

  • **指数增长阶段:**TCP通信初始时,拥塞窗口值为1,随后呈指数级增长。

  • **加法增大阶段:**慢启动阈值的初始值通常设置为对方窗口的最大值(图中为16)。当拥塞窗口达到该阈值时,增长方式由指数增长转变为线性增长。

  • **乘法减小机制:**在线性增长过程中,若发生网络拥塞(如图中拥塞窗口达到24时),慢启动阈值会立即调整为当前拥塞窗口的一半(即12),同时拥塞窗口重置为1。因此,下次拥塞窗口将在达到新阈值12时,由指数增长转为线性增长。

  • **动态调整过程:**网络通信的本质就是不断循环这三个阶段:指数增长→加法增大→乘法减小。

**重要说明:**不同主机的拥塞窗口大小可能存在差异,即使在同一网络区域内的两台主机,其拥塞窗口也可能不同。因此,某些主机可能正在进行正常通信,而另一些主机可能已遭遇网络拥塞。

注意: "乘法减小(Multiplicative Decrease)" + "加法增大(Additive Increase)" 构成了经典的 AIMD(Additive Increase / Multiplicative Decrease) 控制律,是 TCP 拥塞控制稳定性的数学基础。

**简单来说就是:**这种拥塞控制机制,恰如恋爱中的进退之道。

  • TCP连接建立时,慢启动阈值初始值与最大窗口值相等。每次发生超时重传时,慢启动阈值会减半,同时拥塞窗口重置为1。当出现少量丢包时,仅触发超时重传机制;若出现大量丢包,则判定为网络拥塞。

  • 在TCP通信过程中,网络吞吐量呈现先升后降的趋势:初始阶段逐渐提升,一旦检测到网络拥堵便立即下降。究其本质,TCP拥塞控制是一种平衡策略------既要最大化数据传输效率,又要避免给网络带来过大压力。

6、关键细节补充

1. 初始 ssthresh 的设置

  • 传统 TCP:初始 ssthresh = 接收方窗口大小(或一个较大值,如 65535)

  • 现代实现:常设为一个固定大值(如 65535 或更高),让慢启动充分探测

2. 拥塞信号的判断

TCP 将以下事件视为网络拥塞的证据

  • 超时重传 → 严重拥塞

  • 3 个重复 ACK → 轻度/局部拥塞(快重传可处理)

3. 所有 TCP 主机协同工作

  • 拥塞控制不是单机行为,而是分布式协作协议

  • 当网络拥塞时,所有使用 TCP 的主机都会减速,共同缓解压力

  • 这种"自律"机制是互联网能在无中心调度下稳定运行的关键

4. cwnd 与 rwnd 的动态博弈

  • 在低速网络或接收方处理慢时,rwnd 成为瓶颈

  • 在高速网络中,cwnd 通常主导发送速率

  • TCP 自动在两者间取最小值,实现双重保护

7、现代拥塞控制算法的发展

传统 TCP Reno(上述机制)在高带宽、高延迟网络(如卫星链路)中表现不佳。因此衍生出多种改进算法:

算法 特点
CUBIC(Linux 默认) 使用三次函数平滑增长,更适合高速网络
BBR(Google 提出) 基于带宽和 RTT 估计,而非丢包,避免缓冲区膨胀(Bufferbloat)
Westwood 用 ACK 速率估算带宽,更精准调整 cwnd

🌐 尽管算法演进,慢启动 + 拥塞避免 + 快速恢复 + 超时回退 的基本框架仍被广泛沿用。

8、总结:拥塞控制的意义

  1. 防止网络崩溃:通过自律避免"集体踩油门"导致的雪崩。

  2. 公平性保障:多条 TCP 流共享带宽时,能自动趋于公平分配。

  3. 自适应性强:无需网络设备支持,仅靠端系统即可实现。

  4. 与流量控制互补:一个管"网络",一个管"接收方",双保险。

TCP 拥塞控制是分布式系统中"去中心化协作"的典范------没有中央控制器,仅靠每个节点对局部信号(丢包)做出反应,就实现了全局网络的稳定与高效。

相关推荐
航Hang*21 小时前
第三章:综合布线技术 —— 工作区子系统的设计与施工
网络·笔记
读创商闻21 小时前
中广融投让传统文化 “活” 起来
大数据·网络·人工智能
qdprobot21 小时前
开源的在线串口调试助手支持macOS苹果电脑Windows系统Linux 浏览器webSerial
linux·运维·服务器·人工智能·mixly·小智ai·webserial
Geometry Fu21 小时前
《无线传感器网络》WSN 第6讲 IEEE802.15.4通信标准 知识点总结+习题讲解
网络
徐同保1 天前
使用n8n中的HTTP Request节点清空pinecones向量数据库
数据库·网络协议·http
萧技电创EIIA1 天前
西门子modbus Tcp通讯并进行仿真(从站)
网络
饭九钦vlog1 天前
dns形式的floodddos命令
linux·运维·服务器
gaize12131 天前
服务器异常的处理方法
服务器
Anthony_2311 天前
MySql常用SQL命令
服务器·数据库·sql·mysql·http·oracle·udp