众所周知,TCP/IP是面向链接的可靠传输协议,但是问题是如何实现可靠传输的呢?在我看来,TCP/IP可靠传输的基础是滑动窗口协议和连续ARQ协议,配合着流量控制和拥塞控制,使得整个传输过程保证:
所谓停止等待协议就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。但是在传输过程中可能出现意外,这时候就需要用到ARQ协议了,比如说:
这时候A就会有个超时计时器,当超时计时器到期时没收到B的确认报文,则A重新发送 M1 ,因此必须保证以下几点:
发生确认丢失时,B会再一次收到A的重传分组 M1 ,此时B会进行如下行动:
发生确认迟到时,A会再一次收到B的确认报文,这时候A收下并丢弃这个确认报文,并不做什么。
为了提高信道的利用率,实际上采用了流水线传输的方案。如图:
这时就需要使用连续ARQ协议和滑动窗口协议。发送方和接收方各自维持着发送窗口和接受窗口,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。接收方一般采用累计确认方式,即接收方不必对收到的分组逐个发送确认,而是可以在收到几个分组后,对按序到达的最后一个分组发送确认,这样就表示:到这个分组位置的所有分组都已经正确收到了。
由图可见,描述一个发送窗口的状态需要三个指针 P1 、 P2 、 P3
解析一:此时B没有收到序号为31的数据,因此只能对按序收到的数据中的最高的序号给出确认,即此时B的确认号还是30(因为B没有收到序号31的数据,只能发送序号30的确认号)
解析二:此时B收到了序号31的数据,那么B会进行如下处理:
A收到B的确认号后,就可以把发送窗口向前滑动3个序号,但 P2 指针不变
解析三:A在继续发送完序号42~53的数据后,指针 P2 和 P3 重合。发送窗口内的序号都已经用完,但还没有收到确认。由于发送窗口已满,可用窗口已减小到了零,因此必须停止发送。此时A设置了超时计时器,超时计时器到期时就重传这部分数据,重置超时计时器,知道收到B的确认为止。如果A收到的确认号落在发送窗口内,那么A就可以使发送窗口继续向前滑动,并发送新的数据。
发送缓存用来暂时存放(即发送窗口):
接收缓存用来暂时存放:
由上可知,TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段。但是由于TCP的下层互联网环境,发送的报文段可能只经过一个高速率的局域网,也可能经过多个低速率的网络,并且每个IP数据报所选择的路由还可能不同,因此注定超时重传时间要动态变化。
TCP采用的一种自适应算法,每当第一次测量到RTT样本时, RTTs 值就取为所测量到的RTT样本值。但以后每测量到一个新的RTT样本,就按下式重新计算一次 RTTs :
超时计时器设置的超时重传时间应略大于上面得出的 RTTs ,计算公式如下:
RTTD 与 RTTs 和新的RTT样本之差有关。当第一次测量时, RTTD 取值为RTT样本的一般,在以后的测量中按下式计算, 0⩽β<1 ,推荐取值1/4,即0.25:
假设发送出一个报文段。设定的重传时间到了,还没有收到确认。于是重传报文段。经过了一段时间后,收到了确认报文段。
那么,如何判定收到的确认报文是对先发送的报文段的确认,还是对后来重传的报文段的确认?
于是有了Karn算法,即在计算机加权平均 RTTs 时,只要报文段重传了,就不采用其往返时间样本。这样子得出的加权平均 RTTs 和RTO就较准确
但也会引起另外的问题,于是进行修正:报文段每重传一次,就把超时重传时间RTO增大一些,典型的做法就是取新的重传时间为2倍就得重传时间,当不再发生报文段的重传时,才根据上卖弄的式子计算重传时间。
链接建立时,B根据自己的接受缓存大小确定窗口值大小,然后告诉A,我的窗口有多大,然后A就根据B给出的窗口值构造自己的发送窗口(发送缓存不一定比接受缓存大)。如图,窗口有前沿和后沿两个指针,二者都只能前移。
但是前沿指针和后沿指针前移不一定是同步的,可能发生如下情况,关键取决于B告诉A我还能接受多少数据,于是A就根据B提供的信息发送数据,特别注意发送方的发送窗口不能超过接收方给出的额接受窗口的数值。参考如下图:
假如B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储控件。于是B向A发送了rwnd = 400的报文段。然而这个报文段在发送过程中丢失了。酱紫A就一直等待B发送的非零窗口的通知,B也一直等待A发送数据,导致死锁。
因此需要一个持续计时器,当TCP链接的一方收到对方的零窗口通知,就启动持续计时器。持续计时器时间到是就发送一个零窗口探测报文段,而对方就在确认这个探测报文段时给出了现在的窗口值。如果窗口仍为零,那么持续计时器就重新计时。如果不为零,则可以打破死锁。
发送方维持一个拥塞窗口(cwnd)的状态变量。其大小取决于网络的拥塞程度,并且动态的在变化。发送方让自己的发送窗口小于或等于拥塞窗口。
慢开始的算法思路是:
拥塞避免算法的思路是:让拥塞窗口cwnd线性缓慢增长
快重传的算法思路是:
快恢复的算法思路是:
也就是说rwnd和cwnd中较小的一个控制发送方发送数据的速率
随机早期检测RED将TCP拥塞控制和网络层采取的策略联系起来。由于网络层中路由器的队列的尾部丢弃策略会影响TCP的拥塞控制,因此需要采用该策略避免网络中的全局同步现象。
使路由器维持两个参数,即队列长度最小门限 THmin 和最大门限 THmax ,每当一个分组到达时RED组都先计算平均队列长度 LAV ,具体算法思路是:
平均队列长度的计算: