1、什么是拥塞现象?
谈到拥塞控制,我们需要先了解什么是拥塞,拥塞现象简而言之就是网络中的数据包太多,使得网络来不及处理,因为传输的分组在到达某个节点时会有一个缓冲区来保留该分组,当网络中的分组太多,就会导致这个分组没有缓冲区来保存,这样就只能让上个节点重传,但是重传只是徒增网络的压力,并造成恶性循环,就像公路堵车一样。危害嘛,一般会使网络性能下降,严重的话会让网络崩溃,出现死锁现象(网络有效吞吐量接近为零),如果当网络负荷增加到某一个值时,网络的有效吞吐量反而下降了,那就说明该网络出现了拥塞现象。
2、如何解决拥塞现象?
拥塞控制有四个核心算法:慢启动、拥塞避免、快速重传、快速恢复
①慢启动
简单来说就是不要一次性的发送大量数据,就像排洪水,如果排口太大就会冲垮排口,于是慢启动就先对网络中的实际容量进行试探,慢慢增大发送量。
慢启动会给发送方增加一个窗口->拥塞窗口(cwnd),该窗口就是发送方用来进行流量控制的,拥塞窗口初始化为1个报文段,表示只能发送一个报文段,如果发送成功就成指数增加,即(1,2,4,8...)。当然为了防止拥塞窗口增长过大引起网络拥塞,就需要对拥塞窗口设置一个限量->ssthresh状态变量,其作用为:当cwnd<ssthresh,使用慢启动算法,cwnd>ssthresh,使用拥塞避免算法,cwnd=ssthresh,就任选其一。
②拥塞避免算法
拥塞避免算法其实和慢启动算法差不多,当cwnd>ssthresh时,这时就要启动拥塞避免算法,当成功传输一次数据后,慢启动是cwnd以指数增加,而拥塞避免算法只是加1即可,以线性规律增加。
慢启动算法和拥塞避免算法还有一个特点就是在传输过程中发现拥塞现象后,先将ssthresh的值更新成拥塞前ssthresh值的一半,然后将cwnd又重新设置成1,然后继续传输。其实想想也简单,就像我们生活中放水一样,想最快的时间把水放完,但又担心水流太大冲坏东西,就先设一个自己觉得安全的值。于是就开始慢慢放,没到达安全的值就增加的快,超过了安全的值就增速变慢,如果在期间还是水太大冲坏了,就将安全值调的更低,有重新开始放水。
③快速重传
这里我们需要了解一下TCP的超时重传功能,我们知道在发送报文段时,每发送成功一个接收端如果成功收到就会发送相应的ACK,这时如果接收端在一定时间内没有收到该ACK,就会超时重传,这样就会导致我们必须等待设定好的超时时间。快速重传就是比较超时重传的优化。我们发送的报文段都有相应的序号,接受也是按照该序号接受,如果接收方收到了乱序的报文段,即4号之后收到了6,而需要的是5,这就出现了乱序,这时接收方就给发送方发送一个ACK,如果接收方发送了三个相同的ACK,即接收方接受了三次都没有接收到5这个序号的报文段,那么发送方就判定5号报文段丢失,并重发。这样就不用等待计时器结束才知道丢失。
④快速恢复
快速恢复与快速重传相对应,当我们收到了三个相同的ACK,那么又表明了网络并没有拥塞很严重,因为你还可以收到ACK嘛,这时就不用重新回到慢启动了,免得降低效率。这时我们就调整ssthresh = cwnd/2,cwnd = ssthresh + 3,至于为什么加3呢?因为我们收到了三个重复的ACK。就进入快速恢复阶段,于是发送了ACK对应的包,然后如果收到重复得ACK,就cwnd++,当收到了新的ACK,就设置cwnd=ssthresh,然后进入拥塞避免阶段。用网上的一个图来演示下:
这时又发现了问题如果多个包丢失,那么就会持续进入快速恢复阶段,这样cwnd的值就会很低,降低了传输的效率,这时就出现了改进的快速恢复算法。
算法思想:其他的没有变,在收到新的ACK后,之前是退出快速重传阶段,而改进后接收方会把整个已经发送的数据包的ACK发到发送方,如果只能确认发送窗口的部分数据,那么就说明缺少的部分包丢失,并重发。即如果确认所有包,就cwnd=ssthresh,并退出快速恢复算法。如果部分确认,那么cwnd=cwnd-新确认包个数+1,并重发未被确认的第一个包。