tcp之拥塞控制

要了解拥塞控制可以先了解下在途字节数这一概念。

关于TCP拥塞控制的一些术语:

1
2
3
4
5
6
7
8
9
10
SMSS--SENDER MAXIMUM SEGMENT SIZE       发送端可发送的最大分节大小
RMSS--RECEIVER MAXIMUM SEGMENT SIZE 接收端可接收的最大分节大小
FULL-SIZED SEGMENT 一个包含了SMSS字节数据的分节

RECEIVER WINDOW--rwnd 推荐的接收窗口
CONGESTION WINDOW--cwnd: 限制TCP可以发送多少数据的状态变量。在任何时刻TCP不能发送序号大于最大确认序号加上rwnd,cwnd中的的较小值的数据。
INITIAL WINDOW--IW: 初始窗口。三次握手之后的拥塞窗口大小
LOSS WINDOW--LW: 丢失窗口。丢失窗口是在一个TCP根据它的重传定时器检测到了数据丢失之后,拥塞窗口的尺寸
RESTART WINDOW-RW: 重启窗口。重启窗口是TCP在一段闲置期之后重新开始传送后拥塞窗口的尺寸。
FLIGHT SIZE: 在途字节数。已经发送但未确认的数大小

1.拥塞控制的目的
为什么要进行拥塞控制? 假如把网络路径想象成一条河流,发送方是水源,接收方是入海口,那在途字节数就是河里的水量。当水源的流速超过了入海口的流速,河里的水就会越来越多,直到溢出。发生拥塞时的在途字节数就是该时刻的网络拥塞点。发生拥塞时TCP的表现为丢包。当发送方发送数据过慢时,网络等资源就会造成一定的浪费,当发送过快时,就是造成网络拥塞(出现丢包),拥塞控制就是为了找到最合适的发送速度。

2.拥塞控制算法
拥塞控制算法包括4个部分:慢启动,拥塞避免,快速重传,快速恢复。

  • 慢启动与拥塞避免
    慢启动与拥塞避免算法用于控制发送方,避免一下发送过多的数据到网络中。为了实现这些算法,对于每个TCP连接加入这两个变量,cwnd rwnd。另一个状态变量,ssthresh用于标识此时应该使用慢启动(cwnd < ssthresh)还是拥塞避免(cwnd > ssthresh)。

当开始传输数据时,TCP并不知道网络可用的容量,为了避免拥塞,这个阶段TCP会逐渐数据的发送量。慢启动算法为了避免注入过多的数据到网络中会应用于开始传输数据和重传定时器修复丢包之后。

数据传输开始时,IW的大小设置:

1
2
3
4
5
6
If SMSS > 2190 bytes:
IW = 2 * SMSS bytes and MUST NOT be more than 2 segments
If (SMSS > 1095 bytes) and (SMSS <= 2190 bytes):
IW = 3 * SMSS bytes and MUST NOT be more than 3 segments
if SMSS <= 1095 bytes:
IW = 4 * SMSS bytes and MUST NOT be more than 4 segments

在慢启动阶段,TCP通过如下规则在每接收一个ACK时增加cwnd,每次都会增加前一个`cwnd```的一倍大小。

当出现丢包,或者当接收者提示rwnd是受限因素时,或者cwnd > ssthresh时,会进入拥塞避免阶段。

在拥塞避免阶段,在每一个RTT时间,cwnd增加FULL-SIZED SEGMENT大小。

当TCP发送者通过重传定时器意识到丢包时,会重新设置ssthresh的大小。
ssthresh = max (FlightSize / 2, 2*SMSS)

  • 快速重传与快速恢复
    快速重传是为减少丢包重传等待时间的一种机制。如果发送方接收到3个或3个以上的重复ACK,发送方就会重传丢失的数据报,而无需等待超时定时器溢出。
    (1)当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半
    (2)每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送1个分组(如果新的
    cwnd允许发送)
    (3)当下一个确认新数据的ACK到达时,设置cwndssthresh(在第1步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第1个重复的ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半

image
[图片来源网络]


Ref:
1.TCP congestion control
2.RFC2581
3.《TCP/IP协议详解1》