在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP (9)

从这里不难看出,后退n协议一方面因连续发送数据帧而提高了效率,但另一方面,在重传时又必须把原来已正确传送过的数据帧进行重传(仅因这些数据帧之前有一个数据帧出了错),这种做法又使传送效率降低。由此可见,若传输信道的传输质量很差因而误码率较大时,连续测协议不一定优于停止等待协议。此协议中的发送窗口的大小为k,接收窗口仍是1。

 

选择重传协议

在后退n协议中,接收方若发现错误帧就不再接收后续的帧,即使是正确到达的帧,这显然是一种浪费。另一种效率更高的策略是当接收方发现某帧出错后,其后继续送来的正确的帧虽然不能立即递交给接收方的高层,但接收方仍可收下来,存放在一个缓冲区中,同时要求发送方重新传送出错的那一帧。一旦收到重新传来的帧后,就可以原已存于缓冲区中的其余帧一并按正确的顺序递交高层。这种方法称为选择重发(SELECTICE REPEAT),其工作过程如图所示。显然,选择重发减少了浪费,但要求接收方有足够大的缓冲区空间。

在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

流量控制

所谓流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。

 

 

 

在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

上图中,我们可以看到:

接收端LastByteRead指向了TCP缓冲区中读到的位置,NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,我们可以看到中间有些数据还没有到达,所以有数据空白区。

发送端的LastByteAcked指向了被接收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方。

于是:

接收端在给发送端回ACK中会汇报自己的AdvertisedWindow = MaxRcvBuffer – LastByteRcvd – 1;

而发送方会根据这个窗口来控制发送数据的大小,以保证接收方可以处理。

下面我们来看一下发送方的滑动窗口示意图:

TCP窗口info

发送端是怎么做到比较方便知道自己哪些包可以发,哪些包不能发呢?

 

一个简明的方案就是按照接收方的窗口通告,发送方维护一个一样大小的发送窗口就可以了。在窗口内的可以发,窗口外的不可以发,窗口在发送序列上不断后移,这就是TCP中的滑动窗口。如下图所示,对于TCP发送端其发送缓存内的数据都可以分为4类

    [1]-已经发送并得到接收端ACK的; 

    [2]-已经发送但还未收到接收端ACK的; 

    [3]-未发送但允许发送的(接收方还有空间); 

    [4]-未发送且不允许发送(接收方没空间了)。

其中,[2]和[3]两部分合起来称之为发送窗口。

下面两图演示的窗口的滑动情况,收到36的ACK后,窗口向后滑动5个byte。

TCP下面是个滑动后的示意图

 

在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

 

如果接收端通知一个零窗口给发送端,这个时候发送端还能不能发送数据呢?如果不发数据,那一直等接收端口通知一个非0窗口吗,如果接收端一直不通知呢?

下图,展示了一个发送端是怎么受接收端控制的。

在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

由上图我们知道,当接收端通知一个zero窗口的时候,发送端的发送窗口也变成了0,也就是发送端不能发数据了。如果发送端一直等待,直到接收端通知一个非零窗口在发数据的话,这似乎太受限于接收端,如果接收端一直不通知新的窗口呢?显然发送端不能干等,起码有一个主动探测的机制。为解决0窗口的问题,TCP使用了ZWP(Zero Window Probe)。

Zero Window

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjfgz.html