TCP(三 拥塞控制与流量控制)

对于TCP的数据拥堵可以分别在发送方和接收方进行处理,在发送方的处理是拥塞控制,接收方的处理是流量控制,通过这两种机制,有效的确保了TCP的传输效率和可靠性。
拥塞控制 :
TCP基于端到端的拥塞控制方法进行网络拥塞控制,为系统提供了一种根据自己的通信确认报文作为反馈信息来感知网络状态的隐式拥塞控制机制。

慢启动:
当TCP发送方准备发送数据时,若发送方的缓存很大,发送方就将缓存中的数据全部发送到网络,这可能引起网络阻塞。慢启动的基本思想是:先从较小的拥塞窗口(如一个MSS(最大报文段长度))开始,逐步试探网络状况;试探的发送速率要迅速增加,直至解禁某个阈值。对于某个网络来说,它的实际可用带宽要比MSS/RTT大得多,若一线性速度增加来试探网络的发送速率则要经过很长时间才能到达某个阈值,这样会浪费带宽和缓存。
慢启动的算法设计如下:

void solw_start(void){
    Cwin=1 MSS;
    n=0;
    while(没有丢包){
      if(在RTT时间内收到ACK){
        Cwin=Cwin*2^n;//按指数增长
        n++;
        if(Cwin>=sstheesh){//若果窗口大小超过某阈值 执行其他算法
          break;
        }
      }
      else{//若检测到丢包 则重新进行慢启动
        Cwin=1MSS;
      }
  }
}

在达到某个阈值后增长速率就会以每次加1MSS的方式来确定网络的最大发送速率。即在慢启动结束后进入平缓的线性增长的拥塞避免

快速重传:
当某报文段出现丢失事件时,因为超时周期通常比较长,因此发送方要等待很长久时间才能重传丢失的分组。快速重传的思想是:一旦受到某报文的3个冗余ACK,就在该报文段的定时器过期之前重传丢失的报文段。
算法描述:

void additive_increase(void){
event:ACK已到达,其中包括报文段Y的ACK字段
  if(Y > SendBase){
    SendBase=Y;
    if(有当前还没有确认的报文段)
      启动定时器;
  } else{//对已经应答的报文段有冗余ACK
    将受到的Y的计数器加一;
    if(Y的冗余计数器==3){
      重传具有Y序号的报文段;
    }
    break;
  }

}

流量控制
即使TCP提供了可靠传输,但将正确数据放入接收缓存时,如果接收方应用进程正在做其他事情,要过一段时间才能处理缓存数据,或者发送方发的数据又多又快,则很容易使接收缓存区溢出造成丢包。TCP的流量控制可以消除发送方使接收方缓存溢出的可能性。而这种机制就是滑动窗口。

滑动窗口
先来看一个滑动窗口的可视化表示图
TCP(三 拥塞控制与流量控制)_第1张图片
在这个图中,我们将字节聪哥1到11进行标号。接收方提出的窗口称为提出的窗口,它覆盖了4到9字节区域,表明接收方已经确认了包括第三字节在内的数据,且通告窗口为6,发送方计算它的可用窗口,该窗口表明多少数据可以被立即发送。
当接收方确认数据后,这个窗口不时的向右移动,窗口两边的相对运动增加或减少了窗口的大小:
1. 窗口的左边沿向右边沿靠近为窗口合拢。发生在数据被发送和确认是时。
2. 当窗口的右边沿向右移动是则表示允许发送更多的数据,为窗口扩张。这种情况发生在另一端的接收进程读取已经确认的数据并释放了TCP的收缓存时。
3. 当右边沿向左移动时为窗口收缩。
找了一个图来看一下窗口是如何滑动的
TCP(三 拥塞控制与流量控制)_第2张图片
从图中可以看出:
1). 发送方不必发送一个全窗口大小的数据
2). 来自接收方的一个报文段确认数据并把窗口向右滑动。这是因为窗口大小是相对于确认号的。
3). 正如从报文段7到报文段8中变化的那样,窗口的大小可以减小,但是窗口的右边沿缺不能向左移动。
4). 接收方在发送一个ACK前不必等待窗口被填满。
为了进行流量控制,TCP发送方会维护一个变量,该变量称为接收窗口,而这个接收窗口的大小与接收方决定。发送方所发送的数据不能超过接收方缓存的剩余空间大小,接收方缓存的剩余空间大小会随着ACK一起返回给发送方,发送方通过这个大小来调整自己所维护的接收窗口发送数据。

在TCP的流量控制过程中还存在着所谓的TCP糊涂窗口综合征问题。
TCP糊涂窗口综合征:发送方试图尽可能快的向接收方发送数据,而接收方非常忙,不能快速清空自己的缓存。每次发送方发送数据是接收方都会缩小自己的接收窗口,这样发送方的报文段也就越来越小,最后只能发送非常小、效率非常低的报文段 了。
一般通过在TCP发送方进行“抑制”来解决糊涂窗口综合征。即发送方不要求尽可能快的返回确认,而是等有一个合适的缓存长度后才发送确认,这也是通常的Nagle算法:让接收方等待一段时间,只有在接收缓存已经有足够的空间放一个最长的报文段,或者接收缓存已经有一半的空间为空闲时,接收方才发送确认报文段。于是乎就造成了另外一个问题,即应用层的粘包问题

你可能感兴趣的:(linux网络,TCP/IP,计算机网络,tcp,网络,通信)