滑动窗口协议是TCP使用的一种流量控制方法,该协议允许发送方在停止并等待确认前可以连续发送多个分组。

滑动窗口中发送和接受方都会维护一个数据帧的序列,这个序列被称作窗口,你也可以把下图的圆理解成一个多扇窗口的窗子(你开窗户我开窗户,你的窗户和我的窗户有个编号的对应关系,你的每一个数据包必须扔到你我对应的窗口中并进行确认)。

滑动窗口目标检测 滑动窗口技术_tcp流量控制

发送方的窗口大小由接受方确定,目的在于控制发送速度,以免接受方的缓存不够大,而导致溢出,同时控制流量也可以避免网络拥塞。每次完成一个数据包的发送,则窗口的左边缘向右收缩,窗口的右边缘则向右扩展,此时窗口就向前“滑动了”,即下一个数据帧可以被发送。

我们以上图为例做一个简单的分析:

1:初始态,发送方没有帧发出,发送窗口前后沿相重合。接收方0号窗口打开,等待接收0号帧;

2:发送方打开0号窗口,表示已发出0帧但尚确认返回信息。 此时接收窗口状态不变;

3:发送方打开0、1号窗口,表示0、1号帧均在等待确认之列。至此,发送方打开的窗口数已达规定限度,在未收到新的确认返回帧之 前,发送方将暂停发送新的数据帧。接收窗口此时状态仍未变;

4:接收方已收到0号帧,0号窗口关闭,1号窗口打开,表示准备接收1号帧。此时发送窗口状态不 变;

5:发送方收到接收方发来的0号帧确认返回信息,关闭0号窗口,表示从重发表中删除0号帧。此时接收窗口状态仍不变

6:发送方继续发送2号帧,2号窗口 打开,表示2号帧也纳入待确认之列。至此,发送方打开的窗口又已达规定限度,在未收到新的确认返回帧之前,发送方将暂停发送新的数据帧,此时接收窗口状态 仍不变;

7:接收方已收到1号帧,1号窗口关闭,2号窗口打开,表示准备接收2号帧。此时发送窗口状态不变;

8:发送方收到接收方发来的1号帧收毕的确认信 息,关闭1号窗口,表示从重发表中删除1号帧。此时接收窗口状态仍不变。

以上只是滑动窗口协议的理论,实际应用中又有不同:

1.比特滑动窗口协议

当发送窗口和接收窗口的大小固定为1时,滑动窗口协议退化为停等协议(stop-and-wait)。该协议规定发送方每发送一帧后就要停下来,等待接收方已正确接收的确认(acknowledgement)返回后才能继续发送下一帧。由于接收方需要判断接收到的帧是新发的帧还是重新发送的帧,因此发送方要为每一个帧加一个序号。由于停等协议规定只有一帧完全发送成功后才能发送新的帧,因而只用一比特来编号就够了。其发送方和接收方运行的流程图如图所示。

2. 后退n协议

由于停等协议要为每一个帧进行确认后才继续发送下一帧,大大降低了信道利用率,因此又提出了后退n协议。后退n协议中,发送方在发完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发来的应答帧,也可以继续发送。且发送方在每发送完一个数据帧时都要设置超时定时器。只要在所设置的超时时间内仍收到确认帧,就要重发相应的数据帧。如:当发送方发送了N个帧后,若发现该N帧的前一个帧在计时器超时后仍未返回其确认信息,则该帧被判为出错或丢失,此时发送方就不得不重新发送出错帧及其后的N帧。

3.选择重传协议

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

协议改进

由于“滑动窗口”协议的性能取决于窗口大小和网络接收数据包的速度,在流量不稳定的环境中,性能下降甚至可能会使网络发生冲突。 为了避免和提供端到端流量控制,可以建议“慢启动”协议。

对于该协议的改进主要集中在如何减少TCP报文重传方面,目前在TCP中每传输一个报文都要求接收方进行确认,大量短而频繁的确认报文给网络带来了很多开销。因此采取了延迟ACK策略来减少ACK的数量,就是接收方收到一个报文以后,不会立即发送ACK,而是等待1~200ms,这期间若有回送数据报文就捎带确认,但收到两个连续数据报文或者等待超时则发送一个独立确认。有效减少了ACK的数量,改善了TCP的整体性能。

流量控制

流量控制方面主要有两个要点需要掌握。一是TCP利用滑动窗口实现流量控制的机制;二是如何考虑流量控制中的传输效率。

1. 流量控制

所谓流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送.
 这里面涉及到一种情况,如果接受方已经告诉发送方自己的缓冲区已满,于是发送方停止发送数据;等待一段时间后,接受方的缓冲区出现了富余,于是给发送方发送报文告诉发送方可以继续发送了,但是这个报文不幸丢失了,于是就出现发送方等待接受方的通知||接受方等待发送方发送数据的死锁状态。为了处理这种问题,TCP引入了持续计时器(Persistence timer),当发送方收到对方的零窗口通知时,就启用该计时器,时间到则发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。

2. 传递效率

一个显而易见的问题是:单个发送字节单个确认,和窗口有一个空余即通知发送方发送一个字节,无疑增加了网络中的许多不必要的报文(请想想为了一个字节数据而添加的40字节头部吧!),所以我们的原则是尽可能一次多发送几个字节,或者窗口空余较多的时候通知发送方一次发送多个字节。对于前者我们广泛使用Nagle算法,即:

*1. 若发送应用进程要把发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面的字节先缓存起来;
*2. 当发送方收到第一个字节的确认后(也得到了网络情况和对方的接收窗口大小),再把缓冲区的剩余字节组成合适大小的报文发送出去;
*3. 当到达的数据已达到发送窗口大小的一半或以达到报文段的最大长度时,就立即发送一个报文段;

对于后者我们往往的做法是让接收方等待一段时间,或者接收方获得足够的空间容纳一个报文段或者等到接受缓存有一半空闲的时候,再通知发送方发送数据。

参考自http://blog.chinaunix.net/uid-26275986-id-4109679.html