TCP 状态机 / 滑动窗口 / 拥塞控制
TCP 之所以可靠,靠的是三套机制:状态机管连接生命周期、 滑动窗口管流量控制、拥塞控制管网络健康。 下面用三张可交互视图,把这三个抽象机制变成可以亲手操作的东西。
1公式与参数
滑动窗口的吞吐量由窗口大小 $W$ 与往返时延 $\text{RTT}$ 共同决定。 这是"带宽时延积"(BDP)概念的来源:
如果窗口小于 BDP,链路就填不满;如果远大于 BDP,只会白白增加排队时延。最优窗口恰好等于"管道容量"。
拥塞控制的核心是维护一个拥塞窗口 $\text{cwnd}$,实际发送窗口取它与接收窗口的较小值:
$\text{cwnd}$ 由发送方根据网络状况动态调整,$\text{rwnd}$ 由接收方通告。二者取小,既防拥塞又防溢出。
慢启动阶段 $\text{cwnd}$ 每经过一个 RTT 就翻倍(指数增长); 达到慢启动阈值 $\text{ssthresh}$ 后转入拥塞避免,每 RTT 只加 1:
检测到丢包时,TCP 根据信号类型采取不同策略。经典 Tahoe 与 Reno 的差异:
超时是"重度拥塞"信号,cwnd 直接回到 1;收到 3 个重复 ACK 说明只是零星丢包,快速重传只把 cwnd 减半。
| 符号 | 数学含义 | 通俗解释 |
|---|---|---|
| cwnd | 拥塞窗口 | 发送方自己估计"网络还能承受多少"。是 TCP 拥塞控制的核心变量。 |
| rwnd | 接收窗口 | 接收方通告"我缓冲区还能放多少"。防止发送方把接收方撑爆。 |
| ssthresh | 慢启动阈值 | cwnd 超过它就从"翻倍"切到"每次 +1"。是一种保守化的分界线。 |
| RTT | 往返时延 | 一个报文从发出到收到确认的时间。是 TCP 调整速度的基本节拍。 |
| MSS | 最大报文段长度 | 一个 TCP 段最多能装多少数据。窗口大小通常以 MSS 为单位计数。 |
| BDP | 带宽时延积 | 链路上"在途"的比特总量。窗口要接近它才能跑满带宽。 |
| 2MSL | 两倍报文最大生存时间 | TIME_WAIT 状态要等的时长,确保最后一个 ACK 到达对方。 |
| ACK | 确认号 | 告诉对方"这个序号之前的我全收到了"。滑动窗口靠它向前推进。 |
| SYN / FIN | 连接建立 / 关闭标志 | SYN 用来发起连接,FIN 用来请求关闭。它们各消耗一个序号。 |
| RST | 重置 | 强制中断连接。收到 RST 通常意味着对方拒绝或异常。 |
2交互模拟
从 CLOSED 出发,点击左侧事件按钮触发状态转换。 图中的高亮节点是当前状态,黄色边表示从当前状态可用的转换。 完整走一遍"主动打开 → 数据传输 → 主动关闭"能覆盖大部分状态。
每个方块代表一个序号。发送方把窗口内的报文发出去,收到 ACK 后窗口向右滑动。 黄色是"还能发但还没发",蓝色是"已发等 ACK",绿色是"已被确认"。
序列号空间
点「开始模拟」让 cwnd 随时间演化。注意曲线从陡峭到平缓的变化—— 这就是从慢启动切换到拥塞避免的时刻。 设置丢包发生的 RTT,观察 cwnd 如何应声而落。
3深入理解
标准介绍
TCP 由 Cerf 与 Kahn 于 1974 年提出,1981 年 RFC 793 正式标准化。 状态机定义了连接从建立到关闭的 11 个状态及其转换规则, 是 TCP 连接管理的骨架。 滑动窗口由接收方通告窗口(rwnd)实现端到端流量控制, 防止发送方压垮慢速接收方。 拥塞控制由 Jacobson 于 1988 年引入(Tahoe), Reno(1990)增加了快速重传与快速恢复, 后续还有 NewReno、CUBIC、BBR 等演进版本。 这三套机制共同构成了 TCP 可靠传输的基础。
通俗介绍
状态机像打电话的固定流程: 拨号(SYN)→ 对方接听(SYN+ACK)→ 说"喂"(ACK)→ 通话 → 说"拜拜"(FIN)→ 挂断。 每个阶段都有一个状态名,比如"正在拨号中"、"通话中"、"正在挂断中"。 滑动窗口像快递发货:你有一个仓库(序列号空间), 一次最多装一车货(窗口大小),每发一车就等对方签收单。 签收单陆续回来,车子才能继续往前开。 拥塞控制像开车时看路况: 刚上路时不知道堵不堵,先试着加速(慢启动,翻倍); 快到拥堵路段了,就小心翼翼地每次只加一点(拥塞避免); 一旦真堵了(丢包),立刻减速——小事故减半(快速重传), 大事故急刹(超时,退回起点)。
解决了什么问题
- 可靠传输:通过序号、确认、重传,保证数据不丢不重不乱序。
- 连接管理:状态机让双方对"连接处于什么阶段"有一致认知。
- 流量控制:滑动窗口防止快发送方压垮慢接收方。
- 拥塞控制:cwnd 动态调整防止网络整体崩溃(1986 年的拥塞崩溃事件推动了它)。
- 双向对称:同一套机制同时处理发送和接收,两端对等。
为什么重要
- 它是互联网的基石协议:HTTP、HTTPS、SMTP、SSH、FTP 全都建立在 TCP 之上。
- 它是网络课程的核心章节:状态机、滑动窗口、拥塞控制是计算机网络三大必考内容。
- 它是端到端原则的典范:把复杂性放在端点,网络本身保持简单。
- 它是控制论的工程实践:用反馈信号动态调整发送速率,是控制系统思想的经典应用。
- 它的演进持续了 40 多年:从 Tahoe 到 BBR,从未停止优化。
应用场景
- Web 浏览:HTTP/1.1、HTTP/2 都基于 TCP,页面加载速度受 TCP 参数直接影响。
- 文件传输:FTP、SFTP 依赖 TCP 的可靠传输。
- 电子邮件:SMTP、IMAP 使用 TCP 保证邮件不丢。
- 远程登录:SSH、Telnet 需要有序的双向字节流。
- 数据库连接:MySQL、PostgreSQL 的客户端协议都跑在 TCP 上。
- CDN 加速:通过调整初始 cwnd、启用 TCP Fast Open 来降低首包时延。
- 数据中心:DCTCP、CUBIC 等针对短 RTT、高带宽场景优化的拥塞控制算法。
缺陷与局限
- 队头阻塞:TCP 是严格有序的字节流,一个丢包会阻塞后续所有数据交付给应用层。
- 握手延迟:三次握手至少消耗 1.5 个 RTT,短连接场景开销显著。
- TIME_WAIT 占用资源:高并发短连接服务器上大量 TIME_WAIT 会耗尽端口。
- 拥塞控制对无线网络不友好:把无线误码当成拥塞信号,导致不必要的降速。
- 易受攻击:SYN Flood、RST 注入等攻击针对状态机和握手流程。
- 难以支持多路径:传统 TCP 绑定单一路径,MPTCP 的部署仍在推进中。
- 不适合实时应用:重传机制会引入不确定延迟,音视频更倾向 UDP/QUIC。
动手建议
在状态机里走一遍完整的"客户端主动关闭"流程: CLOSED →(主动打开)→ SYN_SENT →(收到SYN+ACK)→ ESTABLISHED → (主动关闭)→ FIN_WAIT_1 →(收到ACK)→ FIN_WAIT_2 →(收到FIN)→ TIME_WAIT → (超时2MSL)→ CLOSED。数一数一共经历了几次状态转换,其中哪些状态会"等待"。 在滑动窗口里把窗口从 2 调到 7: 窗口越大,同时在途的报文越多,观察"窗口利用率"的稳定值是否接近 100%。 然后把 N 调到 16,看完整跑完需要多少步——步骤数大致等于 N 加上窗口的"预热"步数。 在拥塞控制里把 ssthresh 设为 8,丢包 RTT 设为 10,类型选"超时": 你会看到 cwnd 从 1 开始指数增长到 8,然后线性增长,到第 10 个 RTT 时骤降到 1, ssthresh 变成大约 cwnd 的一半。再改成"快速重传", cwnd 只降到 ssthresh+3 而不是 1——这就是 Reno 比 Tahoe 更高效的原因。