TCP的拥塞控制(Congestion Control)是核心机制之一,用于动态调整发送方的数据传输速率,避免网络因过载而出现性能急剧下降(如丢包、延迟激增)。其核心思想是探测网络可用带宽,并在拥塞发生时主动降低速率。以下是TCP拥塞控制的详细解析:
一、拥塞控制的目标
避免拥塞:预防网络进入过载状态。
公平性:多个TCP连接共享带宽时,应公平竞争。
高效性:尽可能利用可用带宽。
二、核心机制
TCP拥塞控制通过拥塞窗口(Congestion Window, cwnd)实现,它限制了发送方未确认数据的最大量(与接收方的滑动窗口共同决定实际发送窗口)。拥塞控制分为四个阶段:
1. 慢启动(Slow Start)
目的:快速探测网络可用带宽。
规则:
初始cwnd = 1 MSS(最大报文段大小,如1460字节)。
每收到一个ACK,cwnd 指数增长(即每RTT翻倍:1 → 2 → 4 → 8...)。
终止条件:
达到慢启动阈值(ssthresh)时,进入拥塞避免阶段。
检测到拥塞(如丢包)时,重置ssthresh = cwnd/2,cwnd = 1,重新慢启动。
2. 拥塞避免(Congestion Avoidance)
目的:线性增长避免触发拥塞。
规则:
每RTT(往返时间)cwnd 增加1 MSS(线性增长,如8 → 9 → 10...)。
终止条件:
发生拥塞(超时或重复ACK)时,调整ssthresh和cwnd。
3. 快速重传(Fast Retransmit)
触发条件:收到3个重复ACK(表明报文段丢失,但后续数据仍能到达)。
动作:
立即重传丢失的报文段(无需等待超时)。
进入快速恢复阶段。
4. 快速恢复(Fast Recovery)
目的:在快速重传后平滑恢复,避免突然降速。
规则:
设置 ssthresh = cwnd/2,cwnd = ssthresh + 3 MSS(补偿已确认的3个重复ACK)。
每收到一个重复ACK,cwnd增加1 MSS。
收到新数据的ACK时,退出快速恢复,进入拥塞避免阶段。
三、拥塞控制的触发事件
超时重传(Timeout):
视为严重拥塞,直接重置 cwnd = 1,重新慢启动。
重复ACK(DupACK):
触发快速重传和快速恢复,对拥塞响应更温和。
四、拥塞控制算法演进
1. Tahoe(早期版本)
发生任何拥塞(超时或重复ACK)均重置cwnd=1,效率较低。
2. Reno(改进版)
引入快速恢复,区分超时和重复ACK,减少激进降速。
3. NewReno(优化版)
改进快速恢复,避免多次丢包时频繁退出恢复阶段。
4. CUBIC(Linux默认)
使用立方函数替代线性增长,更适合高带宽延迟网络(BDP)。
五、实例分析
假设初始参数:cwnd=1 MSS,ssthresh=16 MSS,MSS=1460字节。
慢启动阶段:
发送1个报文 → ACK → cwnd=2 → 发送2个报文 → ACKs → cwnd=4 → ...(指数增长)。
拥塞避免阶段(cwnd≥16):
每RTT cwnd增加1 MSS(如16 → 17 → 18...)。
快速重传与恢复:
若收到3个重复ACK,重传丢失报文,设置cwnd=10(假设原cwnd=20),继续线性增长。
六、拥塞控制 vs. 流量控制
对比项 | 拥塞控制 | 流量控制 |
---|---|---|
目标 | 避免网络过载 | 防止接收方缓冲区溢出 |
控制对象 | 网络链路 | 接收方窗口(rwnd) |
实现机制 | 拥塞窗口(cwnd) | 滑动窗口(Window字段) |
触发信号 | 丢包、延迟增加 | 接收方通告的窗口大小 |
七、关键参数与公式
实际发送窗口:
Window=min(cwnd,rwnd)Window=min(cwnd,rwnd)RTT估算:
SRTT=α×SRTT+(1−α)×NewRTTSRTT=α×SRTT+(1−α)×NewRTT
(α通常为0.875,平滑波动)
八、现代改进方向
BBR(Bottleneck Bandwidth and RTT):
Google提出的算法,基于带宽和延迟探测,替代基于丢包的拥塞控制。
AQM(主动队列管理):
路由器主动丢弃/标记报文(如RED算法),提前避免拥塞。
总结
TCP拥塞控制通过慢启动、拥塞避免、快速重传/恢复的动态调整,在公平性与高效性之间取得平衡。其核心是通过cwnd的增减响应网络状态,确保网络在高负载下仍能稳定运行。