TCP的阻塞控制算法:无控制随便发/固定窗口/慢启动+阻塞避免/快恢复/TCP Cubic/BBR

嘿,大家好!今天咱们聊聊 TCP 拥塞控制和流量算法这个话题。TCP 是互联网的命脉之一,得保证数据顺畅跑,又不能把网络搞瘫。那这些算法咋实现的?有哪些种类?咱们从最简单的想法出发,一步步逼近现在的主流方案,顺便看看每步是怎么改进的。先上个表格,理清思路:

阶段 优势 劣势
无控制随便发 简单,发送端爽快 网络容易堵死,丢包重传效率低
固定窗口 限制发送量,避免一次性塞满网络 窗口死板,适应不了网络变化
慢启动 + 拥塞避免 动态试探网络,丢包后能收敛 丢包反应太猛,恢复慢效率不高
TCP Reno(快恢复) 丢包后恢复快,能更好利用带宽 只看丢包不管原因,误减窗口浪费
TCP Cubic 恢复平稳,抗抖动强,带宽利用好 还是靠丢包判断,根子没变
BBR 不依赖丢包,精准匹配网络状态 实现复杂,对带宽估算要求高

好了,有了这个地图,咱们开始正题,从最朴素的策略聊起,一路推到现在的牛掰方案。


最朴素的开场:随便发,想发多少发多少

想象 TCP 刚起步时,啥规矩没有,发送端跟个愣头青似的,想发多少就发多少。比如我有 10 个数据包,带宽 100Mbps,那就一股脑全扔出去,多痛快!

但问题立马就冒出来了。网络带宽要是只有 50Mbps,或者中间路由器忙不过来,数据包就堆积,队列一满就丢包。丢了包咋办?重传呗。可重传又占资源,网络更堵。这策略的毛病太明显:完全不看网络脸色,容易把路堵死。那咋改进呢?得让发送端有点眼色,感知一下网络状态,别乱来。


第一步:引入窗口,稍微收敛一点

于是就有了个新点子:别一次发太多,定个"窗口",每次就发这么多,等确认收到再发下一波。这就是 TCP 的滑动窗口。比如窗口设成 4 个包,我先发 4 个,收到 ACK(确认)后窗口往前滑,继续发后面的。

这比乱发靠谱多了,至少不会一下把网络塞爆。但窗口大小定死了行不行?比如永远是 4 个包?不行。网络是活的,有时候能撑 8 个包,有时候 2 个包都嫌多,丢包了还得重传,效率低得不行。固定窗口太僵,没法跟上网络节奏 。那咋优化?窗口得活起来,根据网络反馈动态调整


再进一步:慢启动 + 拥塞避免

光有窗口不够,发送端得学会"试探"网络。这就有了"慢启动"(Slow Start)。一开始窗口很小,比如 1 个包,收到 ACK 就翻倍到 2 个,再收到 ACK 变 4 个,指数增长。到了一个阈值(ssthresh),就切到"拥塞避免"(Congestion Avoidance),窗口每次加 1 个,线性增长。

为啥这么搞?慢启动是探路,看看网络能吃下多少。一旦丢包了,说明可能超载,发送端就把窗口砍一半,然后重新进入慢启动,从 1 个包开始试探。比如窗口从 1 到 2、4、8,丢包后砍到 4,再从 1 开始涨到 2、4。这比固定窗口聪明,能自己适应环境。这是 TCP Tahoe 的基本逻辑。

但问题来了:丢包后窗口砍一半,然后直接从 1 个包重新慢启动,是不是有点狠?有时候丢包只是网络抖了一下,不是真堵死,从 1 爬回来太慢,效率不高。反应太简单粗暴,没能充分利用网络潜力 。那优化方向呢?能不能更细致地判断丢包情况,或者丢包后恢复得更快些?


进化版:TCP Reno,快恢复登场

接下来是 TCP Reno,它在 Tahoe 的基础上加了个"快恢复"(Fast Recovery),让丢包处理更聪明。Reno 把丢包分成两种情况:一种是收到三个重复的 ACK(说明丢了一个包,但后面的包还到了),另一种是超时(啥都没收到,网络可能真崩了)。

  • 三个重复 ACK:这说明网络没完全堵死,只是丢了个包。发送端把窗口砍一半,然后进入快恢复,直接线性增长。比如窗口是 10,丢包后收到三个重复 ACK,砍到 5,然后每次加 1,变成 6、7,很快试探回去。
  • 超时:这可能是网络彻底挂了,发送端就老实点,把窗口设回 1,重新慢启动,从 1、2、4 这样涨回来。

举个例子,网络能撑 8 个包,窗口涨到 10 时丢了一个,收到三个重复 ACK,窗口砍到 5,很快加到 6、7、8,比 Tahoe 从 1 爬上来快多了。如果超时了,才会回 1 重启。这比 Tahoe 高明,能更快用上带宽。

但短板呢?Reno 只看丢包,不管丢包为啥发生的 。要是无线网信号差丢的包,Reno 也傻乎乎减窗口,白浪费带宽。优化方向:得更聪明地搞清楚丢包根源,别一刀切


现代主流:TCP Cubic 和 BBR

现在拥塞控制已经很高级了,咱们聊俩代表:TCP Cubic 和 BBR。

TCP Cubic 是现在常见的,比如 Linux 默认用它。它用三次函数控制窗口增长,丢包后减一点(比如乘 0.7),然后快速涨回之前的高点,再放缓。比 Reno 强在哪?恢复平稳,对抖动不敏感,带宽利用率高。

但 Cubic 还是老思路,靠丢包判断拥塞。现代网络丢包不一定是堵了,可能是信号问题。咋办?Google 的 BBR 来了。它不看丢包,直接算网络的瓶颈带宽和最小延迟(RTT),然后贴着这速度发。比如测出带宽 50Mbps,RTT 20ms,就控制在 50Mbps 附近跑,动态调整。结果是丢包少,效率高,尤其在无线网或长距离传输里特别香。


总结:从愣头青到精算师

TCP 拥塞控制的演进就像从愣头青变精算师。一开始乱发,堵了再说;后来加窗口学会试探;再后来分清丢包类型,恢复加速;现在直接算网络能跑多快,精准发力。每步都在解决前面的坑:效率低、反应慢、误判网络。

现代方案的核心:感知网络更聪明,利用带宽更狠,适应场景更灵活。数字上,BBR 在高丢包场景下吞吐量能比 Cubic 高 2-3 倍,延迟降 10 倍,下次视频不卡,记得夸一句:TCP 拥塞控制,真牛!

相关推荐
kfaino3 分钟前
码农的AI翻身(六)你好,我叫 Parameter
后端·aigc
掘金者阿豪6 分钟前
把业务数据变成共享仪表盘:Metabase可视化与远程访问实践
前端·后端
猪猪拆迁队1 小时前
虚拟工厂仿真引擎的架构设计:让一条产线可编程、可观测、可干预
后端·ai编程
字节跳动数据库2 小时前
文章分享——相似函数处理方法
人工智能·后端·程序员
云技纵横2 小时前
@Transactional 失效的 7 种场景:第 5 种最难排查
后端
用户6757049885022 小时前
你知道 Go 结构体和结构体指针调用的区别吗?一文带你彻底搞懂!
后端·go
程序员cxuan2 小时前
读懂 Claude Code 架构分析系列,第一篇,开始!
人工智能·后端·架构
用户6757049885022 小时前
面试官问“装饰器模式”,这样回答薪资多要 3000!
后端
tntxia2 小时前
Geo Scene域名修改引起的一些问题
后端
用户298698530142 小时前
Java 实现 Word 文档加密与权限解除
java·后端