拥塞控制:是指防止过多的数据注入网络,保证网络中的路由器或链路不致过载。出现拥塞时,端点并不了解到拥塞发生的细节,对通信连接的端点来说,拥塞往往表现为通信时延的增加
拥塞控制cwnd是发送方维护的一个状态变量,它会根据网络的拥塞程度动态变化
前面讲到的发送窗口swnd
和接受窗口rwnd
是约等于的关系,这里由于加入了拥塞窗口,因此swnd=min(cwnd,rwnd)
拥塞窗口变化规则
每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小值作为实际发送的窗口
慢启动:TCP在刚建立完连接后,会一点一点的提高发送数据包的数量,随着时间推移数据量会越来越大。具体规则为:当发送方每收到一个ACK,拥塞窗口cwnd大小+1
如下图,假定拥塞窗口cwnd
和发送窗口swnd
相等
可以看出慢启动算法,发送数据包的数量是呈现指数级的增长的,当超过某个阈(慢启动阈值)值时,按照线性方式增长
其中这个阈值就是ssthresh
(slow start threshold
)
cwnd>ssthresh
时,使用慢启动算法cwnd>=ssthresh
时,使用拥塞避免算法拥塞避免:当拥塞窗口cwnd
超过慢启动门限ssthresh
时就会进入拥塞避免算法(一般来说,ssthresh
=65535字节)。具体规则为:每收到一个ACK时,cwnd
增加1/cwnd
接上面的例子,如下图
因此拥塞避免算法将原本慢启动算法的指数级增长变为了线性增长,因此增长速度变得缓慢了很多。
虽然速度变慢了,但是毕竟一直在增长,所以网络就会慢慢进入拥塞的状态,也就会产生丢包,这时就需要对丢失的数据包进行重传
当触发重传时,进入拥塞发生算法
当网络出现拥塞,发生数据包重传,重传方式主要有两种,其对应的拥塞发生算法是不同的
这个时候,ssthresh
和cwnd
的值会发生变化
ssthresh
设为cwnd/2cwnd
重置为1如下图,发生超时重传就意味着“一夜回到解放前”,之后就重新开始了慢启动。这种方式很明显太激进了,几乎是戛然而止,会造成网络卡顿
快速重传算法是当接收方发现丢了一个中间包时,发送三次前一个包的ACK,于是发送单就会快速重传,不必等待超时再重传
TCP认为这种情况不严重,因为大部分没有丢失,于是ssthresh
和cwnd
变化如下
cwnd
=cwnd/2
ssthresh
=cwnd
快速恢复:快速重传和快速恢复算法一般同时使用,快速恢复算法认为,你还能收到3个重复ACK说明网络也不那么糟糕嘛,所以没有必要像超时重传那样强烈
因此首先
cwnd
=cwnd/2
ssthresh
=cwnd
然后进入快速恢复
cwnd
=ssthresh
+3(意思是确认有3个数据包收到了)cwnd+1
cwnd
设置为第一个中的ssthresh
的值,原因是该ACK确认了新的数据,说明从duplicated ACK的数据都已经收到,该恢复过程已经结束,可以回到恢复之前的状态了,也就是再次进入拥塞避免状态。如下图是一个比较经典的拥塞算法的过程图