一、背景介绍
两台主机在传输数据包的时候,如果发送方迟迟没有收到接收方反馈的ACK,那么发送方就会认为它发送的数据包丢失了,进而会重新传输这个丢失的数据包。然而实际情况有可能此时有太多主机正在使用信道资源,导致网络拥塞了,而A发送的数据包被堵在了半路,迟迟没有到达B。这个时候A误认为是发生了丢包情况,会重新传输这个数据包。这样不仅浪费了信道资源,还会使网络更加拥塞。
拥塞控制的出现,减少了网络拥堵,促使网络尽快回复正常。
1、名次解释
- MSS:最大报文长度,这里指报文数据的大小
- ssthresh :慢启动阈值(slow start threshold)
- cwnd:拥塞窗口(Congestion Window),表示一次性连续发送多少个MSS数据包
- RTT:数据完全发送完到收到确认信号的时间
- RTO:超时重传
二、拥塞控制的算法
拥塞控制主要由四个算法组成:
- 慢启动(Slow Start)
- 拥塞避免(Congestion Avoidance)
- 快速重传
- 快速恢复(Fast Recovery)
1、慢启动
慢启动的机制:当TCP连接建立之后,cwnd的大小被初始化为1个最大报文段(MSS)的大小。发送方每收到一次ACK确认之后,就将cwnd的大小增加一个报文段。增加规则如下:cwnd += min(N,MSS)
,N为上次发送被确认的字节数。
慢启动存在的理由是:tcp刚开始并不知道网络的实际情况,需要用一种试探性的方式平滑的增加cwnd的大小。慢启动算法增加了拥塞窗口,可以反应网络的整体情况,而滑动窗口只能反应主机个体情况。
从上述cwnd的增加规则中可以看出,慢启动中cwnd的大小是呈指数级增长的。因此,慢启动并不慢。如果不进行控制,慢启动最终会导致网络拥塞。为了防止这种情况的发生,TCP在拥塞控制中增加了一个变量ssthresh。并且规定了cwnd的大小要按照下述规则进行:
当cwnd<ssthresh时:进行慢启动算法
当cwnd>ssthresh时:进行拥塞避免算法
当cwnd==ssthresh时::两种皆可
2、拥塞避免
cwnd>ssthresh时,进行拥塞避免。拥塞避免即让cwnd缓慢的增长,在一个RTT时间内,将cwnd的大小增加1,即增加cwnd的初始大小。这样,cwnd的大小就从以前的指数级增长变成现在的线性增长。
无论是慢开始还是拥塞避免,只要网络出现阻塞,就将ssthresh的值更新为cwnd的一半,但不能小于2。同时将cwnd的大小更新为1,即为cwnd的初始大小。
3、快速重传
当发送端连续收到3个重复的确认报文端段(3个重复,所以一共收到4个)的时候,tcp就认为拥塞发生了,然后会立即重传丢失的报文段。这个机制不需要等到重传定时器超时,所以叫做快速重传。
此时,
- cwnd大小缩小为当前的一半
- ssthresh设置为缩小后的cwnd大小
- 然后进入快速恢复算法
在TCP报文段丢失或者接收端收到乱序的TCP报文段等情况下,发送端都会收到重复的确认报文段。
4、快速恢复
在进入快速恢复之前,cwnd和ssthresh已经被更改为原有cwnd的一半,即sstresh=cwnd/2
。
- 设置:
cwnd = ssthresh+3*MSS
,加3 * MSS的原因是因为收到3个重复的ACK - 重传DACKs指定的数据包
- 如果再收到DACKs,那么cwnd大小增加一
- 如果收到新的ACK,表明重传的包成功了,那么退出快速恢复算法。将cwnd设置为ssthresh,然后进入拥塞避免算法
三、拥塞控制的状态机
1、Open状态
拥塞控制状态机的默认状态。这种状态下,当ACK到达时,发送方根据拥塞窗口cwnd是小于还是大于慢启动阈值ssthresh,来按照慢启动或者拥塞避免算法来调整拥塞窗口。
2、Disorder状态
当发送方检测到DACK(重复确认)或者SACK(选择性确认)时,状态机将转变为Disorder状态。在此状态下,发送方遵循飞行(in-flight)包守恒原则,即一个新包只有在一个老包离开网络后才发送,也就是发送方收到上一个包的ACK后,才会再发送下一个包。
3、CWR状态
发送方接收到一个拥塞通知时,并不会立刻减少拥塞窗口cwnd,而是每收到两个ACK就减少一个段,直到窗口的大小减半为止。当cwnd正在减小并且网络中有没有重传包时,这个状态就叫CWR(Congestion Window Reduced,拥塞窗口减少)状态。CWR状态可以转变成Recovery或者Loss状态。
4、Recovery状态
当发送方接收到足够(推荐为三个)的DACK(重复确认)后,进入该状态。在该状态下,拥塞窗口cnwd每收到两个ACK就减少一个段(segment),直到cwnd等于慢启动阈值ssthresh,也就是刚进入Recover状态时cwnd的一半大小。 发送方保持 Recovery 状态直到所有进入 Recovery状态时正在发送的数据段都成功地被确认,然后发送方恢复成Open状态,重传超时有可能中断 Recovery 状态,进入Loss状态。
5、Loss状态
当一个RTO到期后,发送方进入Loss状态。所有正在发送的数据标记为丢失,拥塞窗口cwnd设置为一个段(segment),发送方再次以慢启动算法增大拥塞窗口cwnd。
Loss 和 Recovery 状态的区别是:Loss状态下,拥塞窗口在发送方设置为一个段后增大,而 Recovery 状态下,拥塞窗口只能被减小。Loss 状态不能被其他的状态中断,因此,发送方只有在所有 Loss 开始时正在传输的数据都得到成功确认后,才能退到 Open 状态。