当前位置:文档之家› 滑动窗口算法原理

滑动窗口算法原理

1. 滑动窗口算法--------------------------------------------------------------------------------滑动窗口算法工作过程如下。

首先,发送方为每1帧赋一个序号(sequence number),记作S e q N u m 。

现在,让我们忽略S e q N u m是由有限大小的头部字段实现的事实,而假设它能无限增大。

发送方维护3个变量:发送窗口大小(send window size),记作S W S ,给出发送方能够发送但未确认的帧数的上界;L A R 表示最近收到的确认帧(last acknowledgement re c e i v e d)的序号;L F S 表示最近发送的帧(last frame sent)的序号,发送方还维持如下的不变式:LAR-LFR≤RWS当一个确认到达时,发送方向右移动L A R,从而允许发送方发送另一帧。

同时,发送方为所发的每个帧设置一个定时器,如果定时器在A C K到达之前超时,则重发此帧。

注意:发送方必须存储最多S W S个帧,因为在它们得到确认之前必须准备重发。

接收方维护下面3个变量:接收窗口大小(receive window size),记为RW S,给出接收方所能接收的无序帧数目的上界;L A F表示可接收帧(l a rgest acceptable frame)的序号;L F R表示最近收到的帧(last frame re c e i v e d)的序号。

接收方也维持如下不变式:LFS-LAR≤SWS当一个具有顺序号S e q N u m的帧到达时,接收方采取如下行动:如果S e q N u m≤L F R 或S e q N u m > L A F,那么帧不在接收窗口内,于是被丢弃;如果L F R<Se q N u m≤L A F,那么帧在接收窗口内,于是被接收。

现在接收方需要决定是否发送一个A C K。

设S e q N u m To A C K表示未被确认帧的最大序号,则序号小于或等于S e q N u m To A c k的帧都已收到。

即使已经收到更高序号的分组,接收方仍确认S e q N u m To A c k的接收。

这种确认被称为是累积的(c u m u l a t i v e)。

然后它设置L F R = S e q N u m To A c k,并调整L A F = L F R + RW S。

例如,假设L F R= 5(即,上次接收方发送的A C K是为了确认顺序号5的),并且RWS = 4。

这意味着L A F = 9。

如果帧7和8到达,则存储它们,因为它们在接收窗口内。

然而并不需要发送A C K,因为帧6还没有到达。

帧7和8被称为是错序到达的。

(从技术上讲,接收方可以在帧7和8到达时重发帧5的A C K。

)如果帧6当时到达了(或许它在第一次丢失后又重发从而晚到,或许它只是被延迟了),接收方确认帧8,L F R置为8,L A F置为1 2。

如果实际上帧6丢失了,则出现发送方超时,重发帧6。

我们看到,当发生超时时,传输数据量减少,这是因为发送方在帧6确认之前不能向前移动窗口。

这意味着分组丢失时,此方案将不再保证管道满载。

注意:分组丢失时间越长,这个问题越严重。

注意,在这个例子中,接收方可以在帧7刚一到达时就为帧6发送一个认帧N A K(negative acknowl edgment)。

然而,由于发送方的超时机制足以发现这种情况,发送N A K反而为发送方增加了复杂性,因此不必这样做。

正如我们已提到的,当帧7和8到达时为帧5发送一个额外的A C K是合理的;在某些情况下,发送方可以使用重复的A C K作为一个帧丢失的线索。

这两种方法都允许早期的分组丢失检测,有助于改进性能。

关于这个方案的另一个变种是使用选择确认(selective acknowledgements)。

即,接收方能够准确地确认那些已收到的帧,而不只是确认按顺序收到最高序号的帧。

因此,在上例中,接收方能够确认帧7、8的接收。

如果给发送方更多的信息,就能使其较容易地保持管道满载,但增加了实现的复杂性。

发送窗口大小是根据一段给定时间内链路上有多少待确认的帧来选择的;对于一个给定的延迟与带宽的乘积,S W S是容易计算的。

另一方面,接收方可以将RW S设置为任何想要的值。

通常的两种设置是:RW S= 1,表示接收方不存储任何错序到达的帧;RW S=S W S,表示接收方能够缓存发送方传输的任何帧。

由于错序到达的帧的数目不可能超过S W S个,所以设置RWS >S W S没有意义。

2. 有限顺序号和滑动窗口--------------------------------------------------------------------------------现在我们再来讨论算法中做过的一个简化,即假设序号是可以无限增大的。

当然,实际上是在一个有限的头部字段中说明一个帧的序号。

例如,一个3比特字段意味着有8个可用序号0 ~ 7。

因此序号必须可重用,或者说序号能回绕。

这就带来了一个问题:要能够区别同一序号的不同次发送实例,这意味着可用序号的数目必须大于所允许的待确认帧的数目。

例如,停止等待算法允许一次有1个待确认帧,并有2个不同的序号。

假设序号空间中的序号数比待确认的帧数大1,即S W S ≤M A a x S e q N u m -1 ,其中M a x Seq N u m 是可用序号数。

这就够了吗?答案取决于RW S 。

如果RW S = 1,那么MaxSeqNum≥SWS+1是足够了。

如果RW S等于S W S,那么有一个只比发送窗口尺寸大1的M a x S e q N u m是不够的。

为看清这一点,考虑有8个序号0 ~ 7的情况,并且S W S = RW S = 7。

假设发送方传输帧0 ~ 6,并且接收方成功接收,但A C K丢失。

接收方现在希望接收帧7,0 ~ 5,但发送方超时,然后发送帧0 ~ 6。

不幸的是,接收方期待的是第二次的帧0 ~ 5,得到的却是第一次的帧0 ~ 5。

这正是我们想避免的情况。

结果是,当RW S = S W S时,发送窗口的大小不能大于可用序号数的一半,或更准确地说,SWS<(Maxseqnum+1)/2直观地,这说明滑动窗口协议是在序号空间的两半之间变换,就像停止等待协议的序号是在0和1之间变换一样。

唯一的区别是,它在序号空间的两半之间连续滑动而不是离散的变换。

注意,这条规则是特别针对RW S = S W S的。

我们把确定适用于RW S和S W S的任意值的更一般的规则留做一个练习。

还要注意,窗口的大小和序号空间之间的关系依赖于一个很明显以至于容易被忽略的假设,即帧在传输中不重新排序。

这在直连的点到点链路上不能发生,因为在传输过程中一个帧不可能赶上另一个帧。

然而,我们将在第5章看到用在一个不同环境中的滑动窗口算法,并且需要设计另一条规则。

3. 滑动窗口的实现--------------------------------------------------------------------------------下面的例程说明我们如何实现滑动窗口算法的发送和接收的两个方面。

该例程取自一个正在使用的协议,称为滑动窗口协议S W P(Sliding Window Pro t o c o l)。

为了不涉及协议图中的邻近协议,我们用H L P(高层协议)表示S W P上层的协议,用L I N K(链路层协议)表示S W P下层的协议。

我们先定义一对数据结构。

首先,帧头部非常简单:它包含一个序号(S e q N u m)和一个确认号(A c k N u m)。

它还包含一个标志(F l a g s)字段,表明帧是一个A C K帧还是携带数据的帧。

其次,滑动窗口算法的状态有如下结构。

对于协议发送方,该状态包括如上所述的变量L A R和L F S,以及一个存放已发出但尚未确认的帧的队列(s e n d Q)。

发送方状态还包含一个计数信号量(counting semaphore),称为s e n d Wi n d o w N o t F u l l。

下面我们将会看到如何使用它,但一般来说,信号量是一个支持s e m Wa i t和s e m S i g n a l操作的同步原语。

每次调用S e m S i g n a l,信号量加1,每次调用S e m Wa i t,信号量减1。

如果信号量减小,导致它的值小于0,那么调用进程阻塞(挂起)。

一旦执行了足够的s e m S i g n a l 操作而使信号量的值增大到大于0,在调用s e m Wa i t的过程中阻塞的进程就允许被恢复。

对于协议的接收方,如前所述,该状态包含变量L F R ,加上一个存放已收到的错序帧的队列(r e c v Q)。

最后,虽然未显示,发送方和接收方的滑动窗口的大小分别由常量S W S 和RW S表示。

S W P的发送方是由s e n d S W P过程实现的。

这个例程很简单。

首先,s e m Wa i t使这个进程在一个信号量上阻塞,直到它可以发另一帧。

一旦允许继续,s e n d S W P设置帧头部中的顺序号,将此帧的拷贝存储在发送队列(s e n d Q)中,调度一个超时事件以便处理帧未被确认的情况,并将帧发给低层协议。

值得注意的一个细节是刚好在调用m s g A d d H d r之前调用s t o r e _ s w p _ h d r。

该例程将存有S W P头部的C语言结构(s t a t e - > h d r)转化为能够安全放在消息前面的字节串(h b u f)。

该例程(未给出)必须将头部中的每一个整数字段转化为网络字节顺序,并且去掉编译程序加入C语言结构中的任意填充。

7 . 1节将详细讨论字节顺序的问题,但现在,假设该例程将多字整数中最高有效位放在最高地址字节就足够了。

这个例程的另一个复杂性是使用s e m Wa i t 和s e n dW i n d o w N o t F u l l 信号量。

S e n dWi n d o w N o t F u l l被初始化为发送方滑动窗口的大小S W S(未给出这一初始化)。

发送方每传输一帧,s e m Wa i t操作将这个数减1,如果减小到0,则阻塞发送方进程。

每收到一个A C K,在d e l i v e r S W P中调用s e m S i g n a l操作(见下面)将此数加1,从而激活正在等待的发送方进程。

在继续介绍S W P的接收方之前,需要调整一个看上去不一致的地方。

相关主题