慢启动 && 拥塞避免 | 快速重传 && 快速恢复
愿打开这篇对你有帮助。
之前在 《再探TCP/IP》那篇里面写过,但是写的我自己的都看不懂了,重新整理一下。
@[toc]
概念清晰
拥塞控制:==为了防止过多的数据注入到网络中==。拥塞控制要做的都有一个前提:就是网络能够承受现有的网络负荷。对比流量控制:==拥塞控制是一个全局的过程,涉及到所有的主机、路由器、以及降低网络相关的所有因素==。流量控制往往指点对点通信量的控制。是端对端的问题。
拥塞窗口:发送方为一个动态变化的窗口叫做拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度。发送方让自己的发送窗口=拥塞窗口,但是发送窗口不是一直等于拥塞窗口的,在网络情况好的时候,拥塞窗口不断的增加,发送方的窗口自然也随着增加,但是接受方的接受能力有限,在发送方的窗口达到某个大小时就不在发生变化了。
网络拥塞:发送方发送一些报文段时,如果发送方没有在时间间隔内收到接收方的确认报文段,则网络拥塞。
慢启动:主机开发发送数据报时,如果立即将大量的数据注入到网络中,可能会出现网络的拥塞。慢启动算法就是在主机刚开始发送数据报的时候先探测一下网络的状况,如果网络状况良好,发送方每发送一次文段都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小,即增加发送窗口的大小。
文字看的麻烦的话,直接看图(理想状态下的图):
前期指数增长,到达阈值之后,就以一个一个线性的速度来增长。我们也把指数增长阶段称之为慢启动,线性增长阶段称之为拥塞避免。
图解
图在上面。
如果立即将大量的数据注入到网络可能会出现网络的拥塞。慢启动算法就是在刚开始发送数据报的时候先探测一下网络的状况,如果网络状况良好,发送方每发送一次报文都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小,即增加发送窗口的大小。发送方先设置拥塞窗口cwnd=1, 发送第一个报文段M1,接收方接收到M1后,发送方接收到接收方的确认后,把cwnd增加到2,接着发送方发送M2、M3,发送方接收到接收方发送的确认后cwnd增加到4,慢启动算法每经过一个传输轮次(认为发送方都成功接收接收方的确认),拥塞窗口cwnd就加倍。
为了防止拥塞窗口cwnd增加过快而导致网络拥塞,所以需要设置一个慢开始门限ssthresh状态变量:
1. 当cwnd < ssthresh,使用慢启动算法,
2. 当cwnd > ssthresh,使用拥塞避免算法,停用慢启动算法。
3. 当cwnd = ssthresh,这两个算法都可以。
拥塞避免的思路:是让cwnd缓慢的增加而不是加倍的增长,每经历过一次往返时间就使cwnd增加1,而不是加倍,这样使cwnd缓慢的增长,比慢启动要慢的多。
上面这是理想状态,出现网络拥塞又是另一种情况了。
出现变故
无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限ssthresh为设置为发送窗口的一半,cwnd设置为1,然后在使用慢启动算法,这样做的目的能迅速的减少主机向网络中传输数据,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。
快速重传
我们都知道,数据包是有序号的,如果A给B发送M1, M2, M3, M4, M5…N个数据包,如果B收到了M1, M2, M4…却始终没有收到M3,这个时候就会重复确认M2,意在告诉A,M3还没收到,可能是丢失。这时候就需要立即重传丢失的数据段,这个地方不用等待定时器溢出。
快速恢复
快速重传和快速恢复算法一般同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈,并不需要重新回到慢启动进行,这样可能降低效率。所以协议栈会做如下工作
-
cwnd = cwnd/2
-
sshthresh = cwnd
然后启动快速恢复算法:
-
设置cwnd = ssthresh+ACK个数*MSS(一般情况下会是3个dup ACK)
-
重传丢失的数据包(对于重传丢失的那个数据包,可以参考TCP-IP详解:SACK选项)
-
如果只收到Dup ACK,那么cwnd = cwnd + 1, 并且在允许的条件下发送一个报文段
-
如果收到新的ACK, 设置cwnd = ssthresh, 进入拥塞避免阶段
对于Reno、AIMD 这些算法,我看到有一个大佬(目前CSDN总排前十的某位很有个性的大佬)提出了自己的想法,说是这些算法只是数学层面的收敛算法,正好TCP就需要收敛罢了,根本不能对网络拥塞做出判断。
这个我得再去研究研究,所以这篇先到这里。
- 点赞
- 收藏
- 关注作者
评论(0)