当前位置: 首页 > news >正文

《深入理解 RFC 5681:TCP 拥塞控制》

“网络是共享的,谁也不能太贪婪。”—— TCP 拥塞控制的哲学

朋友们好,今天我们来啃一份互联网世界的“红绿灯规范”——RFC 5681。如果你写过网络程序、调过 TCP 参数、或者只是好奇为什么你在看视频时网络不会突然崩溃,那这篇都值得一读。


一、它是什么?

表格

问题答案
RFC 编号5681
全称TCP Congestion Control(TCP 拥塞控制)
状态📘 互联网标准(Standards Track)
发布时间2009 年 9 月(距今已有十余年,但依然核心)
废除了谁RFC 2581(又废除了 RFC 2001)
一句话定位给 TCP 装上一个“智能油门”,既不浪费带宽,也不撑爆网络。

🔑 核心要解决三个问题

  1. 新连接怎么开始发数据?—— 答案:慢启动(Slow Start)
  2. 出现丢包如何应对?—— 答案:快速重传 + 快速恢复(Fast Retransmit/Fast Recovery)
  3. 空闲太久后怎么恢复?—— 答案:重启窗口(Restart Window)

二、核心机制:四个算法,一张流程图

🚦 发送端的生命周期

+------------------+ | 连接建立完成 | | cwnd = IW | +--------+---------+ | cwnd < ssthresh? ┌──── YES ──┴── NO ─────┐ ↓ ↓ +------------------+ +------------------+ | 慢启动 | | 拥塞避免 | | 每 RTT 翻倍 cwnd | | 每 RTT +1 SMSS | +--------+---------+ +--------+---------+ | | +------ 丢包发生? ---------+ | +--------+---------+ | 检测到丢包方式 | +----+----+----+----+ | | | ┌────+ + +────┐ ↓ ↓ ↓ 3个重复ACK 超时 SACK/ECN | | +---------+ +---------+ | 快速重传&恢复 | 重置 cwnd=1 | cwnd 减半 | 重新慢启动 +------------------+

🧊 生活类比:高速公路的智能限速

想象你在一条高速上开车,cwnd(拥塞窗口)是你能同时在路上跑的“车数”的许可证。

  • 慢启动:刚上高速,每次前车到达目的地(收到 ACK),你就多放两辆车出去——指数级放行,快速试探道路容量。
  • 拥塞避免:当发现路上车已经不少了(cwnd 超过阈值),改为每次前车到了才多放一辆——线性增长,保守试探。
  • 丢包 = 车祸:收到 3 个重复 ACK 相当于“后面连续来的车都报告前面有事故”——立即降速到一半,并补发丢失的车。
  • 超时 = 彻底堵死:很久没收到任何反馈,只能停车(cwnd=1),从头探路。

三、三个关键窗口和两个阈值

cwnd(拥塞窗口)

TCP 发送端的状态变量,限制“已发送但未确认”的数据量。升升降降全看网络脸色。

ssthresh(慢启动阈值)

  • 初始时设为极大值(通常是最大通告窗口)
  • 丢包时设为max(FlightSize / 2, 2 × SMSS)
  • 决定使用慢启动还是拥塞避免的分水岭

FlightSize(在途数据)

“已发出但未收到累计确认”的数据量。注意:很多实现错误地用了 cwnd 来计算 ssthresh,这是不对的,应该用 FlightSize。


四、开发者必看:5 个最容易踩的坑

🕳️ 坑 1:初始窗口不是固定的“3 段”

很多人背了“初始窗口是 3 段”的口诀,但标准明确分三档:

SMSS > 2190 → IW = 2 × SMSS 1095 < SMSS ≤ 2190 → IW = 3 × SMSS SMSS ≤ 1095 → IW = 4 × SMSS

如果你用了巨型帧(SMSS 很大),初始窗口可能是2 段而不是 3 段!

🕳️ 坑 2:超时后 ssthresh 不是每次都减半

第一次超时:

ssthresh = max(FlightSize / 2, 2 * SMSS) cwnd = 1 * SMSS

但如果是同一段数据第二次超时

  • ssthresh 保持原值,不再减半
  • 只有 cwnd 重置到 1

实现时要注意区分“同一段的重传”和“新段的超时”。

🕳️ 坑 3:拥塞避免阶段的 ACK 计数要小心

拥塞避免期增加 cwnd 有两种主流方式:

  1. 字节计数法(推荐):累计确认字节数,达到 cwnd 后加 1 SMSS
  2. 公式法cwnd += SMSS * SMSS / cwnd

注意:整数运算中,当cwnd > SMSS * SMSS时公式可能返回 0,标准要求round up 到 1 字节

🕳️ 坑 4:延迟确认的两个“紧箍咒”

  • 每两个全尺寸段必须至少发一个 ACK(SHOULD)
  • 等待 ACK 不得超过 500ms(MUST)

如果接收方 MSS 很大但发送方实际段很小,会导致“延展 ACK”问题——性能可能严重退化。

🕳️ 坑 5:空闲重启的误区

TCP 闲置超过一个 RTO 后,发送方的 cwnd 必须“缩水”到:

RW = min(IW, cwnd)

但标准特别提醒:应该以“上次发送数据”为准,而不是“上次接收数据”。否则持久 HTTP 连接中,服务器收到请求后可能误以为连接“不是空闲”,用过大窗口发送,造成突发拥塞。


五、协议间的配合关系

RFC 5681 不是孤立存在的,它依赖于一大套 RFC 家族:

表格

相关 RFC作用
RFC 793TCP 基础——序列号、确认号、窗口
RFC 1122主机要求——强制要求拥塞控制实现
RFC 1191 / 4821路径 MTU 发现——决定 SMSS
RFC 2988重传定时器——RTO 计算
RFC 3042Limited Transmit——前 2 个 dup ACK 时发新数据
RFC 3465Appropriate Byte Counting——增强 cwnd 增长鲁棒性
RFC 3390增大初始窗口——本标准的 IW 依据
RFC 3517 / 3782高级丢包恢复算法(SACK-based / NewReno)

六、安全考虑:破坏者能做什么?

如果用一句话回答:RFC 5681 设计的拥塞控制对整个互联网的稳定性至关重要。

攻击者可以通过伪造重复 ACK让发送方膨胀 cwnd,或通过ACK 分割攻击(ACK Division)诱导发送方过快增长窗口。

标准给出的防御手段:使用 Appropriate Byte Counting(RFC 3465),即按字节计数而非按段计数来增加窗口,这样做可以在一定程度上抵御恶意接收者通过“分拆确认”来欺骗发送方。


🎯 一句话记住这个协议

RFC 5681 就是 TCP 的“自动驾驶系统”——用慢启动试探路况、用拥塞避免保持稳定、用快速重传及时纠错、用快速恢复避免过度刹车。


本文基于 RFC 5681(September 2009)撰写,已考虑最新勘误与配套 RFC。你需要进一步了解某个算法的细节(如 NewReno vs SACK 的差异、或 ECN 的配合)吗?欢迎留言或私信。

http://www.jsqmd.com/news/1137161/

相关文章:

  • NetworkNightmare终极指南:网络渗透测试思维导图完整解析
  • 为什么你需要一个专业的B站视频下载工具?bilidown给你答案
  • 嵌套函数的例子
  • WAIC 2026 聚焦具身智能:破技术、数据、量产难题,迈向工业化时刻
  • 30分钟构建企业级监控系统:VictoriaMetrics实战完全指南
  • 面向对象-----继承
  • 终极Windows自动化部署指南:揭秘unattend-generator如何让批量配置变得如此简单!
  • SAM2Act 项目介绍、最小成本复现、工业落地与轻量模型对比
  • SDF在游戏开发中的创新应用:Dreams与Claybook技术案例分析
  • 151、RAG 检索增强生成(五):评估体系——RAGAS 指标、人工评测与线上监控
  • GeoQ高级功能:地理空间分析、标记和社交标签系统详解
  • UI.Vision RPA:免费开源自动化工具终极指南
  • 企业级应用一键部署:使用ansible-playbooks快速搭建Odoo ERP与Phabricator代码审查系统
  • 2026最新8款学生免费AI编程软件权威实测:校园项目平替全汇总
  • Boss Show Time终极指南:5分钟掌握四大招聘平台职位发布时间显示插件
  • 如何用RxjavaRetrofitDemo封装统一网络请求?手把手教你打造高效架构
  • AIGC 辅助简历优化:ChatGPT 4.0 与 Kimi 在技术经历提炼中的3种Prompt实战
  • 【Bug已解决】OpenClaw 报错 System-level gateway service detected 解决方案
  • iOS条码扫描终极指南:ZXingify-ObjC让你的应用瞬间拥有专业识别能力
  • DeepFace模型训练优化:从入门到精通的5个实战技巧
  • EarlyBird误报处理完全指南:精准过滤与智能分析的最佳实践
  • 解锁被封印的电池生命:Open Battery Information 让你的BMS重获新生
  • 仲景中医AI大模型:5分钟开启智能中医助手新时代
  • AMP by Example实战:使用amp-img组件优化图片加载的10个技巧
  • Escrcpy:3个维度重新定义Android设备桌面化体验
  • 解决iOS图片局部模糊难题:UIImage-BlurredFrame实战案例
  • EMA 与 SWA 对比:在 Stable Diffusion 3 微调中提升 FID 分数的2种策略
  • CDDStore扫一扫功能实现:二维码扫描在电商场景中的应用
  • 工业级AI Agent平台架构设计:从任务编排到系统落地的工程实践
  • 终极指南:深度实战HIP协作组编程,解决GPU并行计算中的线程同步难题