一:TCP的拥塞控制
1:是什么
(1):是什么(拥塞现象)
网络的 吞吐量 与 通信子网 负荷(即通信子网中正在传输的分组数)有着密切的关系。当 通信子网 负荷比较小时,网络的 吞吐量 (分组数/秒)随网络负荷(每个 节点 中分组的平均数)的增加而线性增加。当网络负荷增加到某一值后,若 网络吞吐量 反而下降,则表征网络中出现了拥塞现象。在一个出现拥塞现象的网络中,到达某个 节点 的分组将会遇到无缓冲区可用的情况,从而使这些分组不得不由前一节点重传,或者需要由源节点或源 端系统 重传。当拥塞比较严重时, 通信子网 中相当多的传输能力和 节点 缓冲器都用于这种无谓的重传,从而使通信子网的有效 吞吐量 下降。由此引起恶性循环,使 通信子网 的局部甚至全部处于 死锁 状态,最终导致网络有效 吞吐量 接近为零。(百度百科)
(自我理解)
当网络的吞吐量达到一定的限制后,会发生拥塞现象,那么此时发送的数据包会因为延迟无法到达接收端,因为超时重传机制所以发送端会重新发送数据包,那么网络带宽中本来就很拥塞,那么的话再发数据包就会更加拥塞,由此会形成恶性循环,如果不加控制的话,那么最终网络的有效吞吐量将接近为0.
2:拥塞中的相关概念
(1):cwnd
这个是一个发送方维护的一个状态变量,他会根据网络的拥塞程度动态变化。(刚开始的时候cwnd是不断增长的,直到遇到拥塞就会发生相应的调整)
发送窗口 swnd 和接收窗口 rwnd 是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是
swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。
3:如何知道网络中是否发生了拥塞
其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传(快速重传),就会认为网络出现了用拥塞。
4:如何控制网络拥塞
(1):拥塞控制算法简介
拥塞控制的过程分为四个阶段:慢启动、拥塞避免、拥塞发生(快重传),快恢复
a:慢启动
慢启动阶段思路是不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小,在没有出现丢包时每收到一个 ACK 就将拥塞窗口大小加一(单位是 MSS,最大单个报文段长度),每轮次发送窗口增加一倍,呈指数增长,若出现丢包,则将拥塞窗口减半,进入拥塞避免阶段;
b:拥塞避免和快重传
当窗口达到慢启动阈值或出现丢包时,进入拥塞避免阶段,窗口每轮次加一,呈线性增长;当收到对一个报文的三个重复的 ACK 时,认为这个报文的下一个报文丢失了,进入快重传阶段,要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认;
c:快恢复
快重传完成后进入快恢复阶段,将慢启动阈值修改为当前拥塞窗口值的一半,同时拥塞窗口值等于慢启动阈值,然后进入拥塞避免阶段,重复上述过程
(2):慢启动
TCP 在刚建立连接完成后,首先是有个慢启动的过程,这个慢启动的意思就是一点一点的提高发送数据包的数量,如果一上来就发大量的数据,这不是给网络添堵吗?
慢启动的算法记住一个规则就行:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。
这里假定拥塞窗口 cwnd 和发送窗口 swnd 相等,下面举个栗子:
-
连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。
-
当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这一次能够发送 4 个
-
当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4 个,所以这一次能够发送 8 个。
可以看出慢启动算法,发包的个数是指数性的增长。
“ 那慢启动涨到什么时候是个头呢?
”
有一个叫慢启动门限(慢启动阙值) ssthresh (slow start threshold)状态变量。
当 cwnd < ssthresh 时,使用慢启动算法。当 cwnd >= ssthresh 时,就会使用「拥塞避免算法」
(3):拥塞避免算法
当拥塞窗口 cwnd 「超过」慢启动门限 ssthresh 就会进入拥塞避免算法。
一般来说 ssthresh 的大小是 65535 字节。
那么进入拥塞避免算法后,它的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd
示例:
接上前面的慢启动的栗子,现假定 ssthresh 为 8:
当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长
所以,我们可以发现,拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,还是增长阶段,但是增长速度缓慢了一些。
就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。
当触发了重传机制,也就进入了「拥塞发生算法」。
(4):拥塞发生(快重传或超时重传)
「快速重传算法」。当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。
TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 ssthresh 和 cwnd 变化如下:
cwnd = cwnd/2 ,也就是设置为原来的一半;
ssthresh = cwnd;进入快速恢复算法
(5):快速恢复
快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕
正如前面所说,进入快速恢复之前,cwnd 和 ssthresh 已被更新了:
cwnd = cwnd/2 ,也就是设置为原来的一半;
ssthresh = cwnd;
然后,进入快速恢复算法如下:
拥塞窗口 cwnd = ssthresh + 3 ( 3 的意思是确认有 3 个数据包被收到了);
-
重传丢失的数据包;
-
如果再收到重复的 ACK,那么 cwnd 增加 1;
-
如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态; (当重新接收到ACK的话说明传输数据包已经正常,那么就可以恢复到之前的状态拥塞状态)
参考自