目录
一、拥塞控制概述
1. 如何限制发送方发送速率
TCP 拥塞控制设置 拥塞窗口 变量,表示为 cwnd:
- 它对发送方向网络中发送流量的速率进行了限制
- 发送方中未被确认的数据量不会超过 cwnd 和 rwnd 中的最小值
LastByteSent - LastByteAcked < min{CongWin, RcvWindow}
我们后面假设接收缓冲区足够大,以至可以忽略接收窗口 rwnd 的限制,因此在发送方中未被确认的数据量仅受限于拥塞窗口 cwnd 。
2. 发送方如何感知到拥塞
定义 丢包事件 为:
- 超时
- 三个重复的 ACK
一旦发生丢包事件,发送方就认为在发送方到接收方的路径上出现了拥塞。
3. 发送发如何选择发送速率
① 一个丢失的报文段意味着拥塞,因此当丢失报文段时应当降低 TCP 发送方的速率。
② 一个确认报文段指示该网络正在向接收方交付发送方的报文段,因此,当对先前未确认报文段的确认到达时,能够增加发送方的速率。
二、TCP 拥塞控制算法
1. 慢启动
① 增长方式
初始速率慢但以指数增长
连接开始时,设置 cwnd = 1MSS,则发送速率为 1MSS/RTT;假设 MSS=500B 且 RTT=200ms,则初始发送速率为 20Kbps,远远小于有效带宽。因此,希望尽快达到期待的速率,故将以二的指数方式增加速率。
工作方式:cwnd 的值以 1 个 MSS 开始并且每当传输的报文段首次被确认就增加 1 个 MSS 。
② 停止增长
(Tahoe 版) 检测到丢包事件时:
- 将慢启动阈值 ssthresh 设置为 cwnd/2
- 将 cwnd 重置为 1 并重新开始慢启动
为什么分开处理?因为三次重复确认表示网络还具有一定的数据传输能力
③ 加性递增,乘性递减
- 加性递增:每个 RTT 内收到一个确认,拥塞窗口就增加一个 MSS
- 乘性递减:发生丢包事件后将慢启动阈值 ssthresh 减半
④ 由指数增长到线性增长
当检测到拥塞时 ssthresh 被设置为 cwnd/2,当 cwnd 从头开始重新增加并达到 ssthresh 时,继续让 cwnd 指数增长是很危险的,因为一个 RTT 就会使 cwnd 达到之前拥塞时的值。因此,我们需要结束慢启动并转移到拥塞避免模式。
2. 拥塞避免
- 当 cwnd 低于阀值,发送方处于慢启动阶段,窗口指数增长;
- 当 cwnd 高于阀值,发送方处于拥塞避免阶段,窗口线性增长。
① 增长方式
工作方式:每个 RTT 只将 cwnd 的值增加一个 MSS,即发送 N 个报文段,每到达一个 ACK 就增加 1/N 个 MSS 的拥塞窗口长度。
② 停止增长
(Reno 版) 检测到超时时:
- 将慢启动阈值 ssthresh 设置为 cwnd/2
- 将 cwnd 重置为 1 并进入快速恢复
(Reno 版) 检测到三次重复确认时:
- 将慢启动阈值 ssthresh 设置为 cwnd/2
- 将 cwnd 设置为 cwnd/2+3 并进入快速恢复
3. 快速恢复
专门针对慢启动和拥塞控制状态中的三个重复确认事件
① 丢失报文段的 ACK 到达之前:
每当收到一个冗余的 ACK,cwnd 的值增加一个 MSS
居然是指数增长
② 丢失报文段的 ACK 到达之前出现丢包事件:
重传之后又超时了或者新报文段的 ACK 超时了
- 将慢启动阈值 ssthresh 设置为 cwnd/2
- 将 cwnd 重置为 1 并进入慢启动
③ 丢失报文段的 ACK 到达之后:
降低 cwnd 后进入拥塞避免状态
4. 状态转换图
5. 拥塞窗口的变化举例
第八轮发生的是三个重复确认事件