传输的可靠性
在通信过程中,帧的传输而可能出错时,可以用像CRC这样的差错码来检测。但是虽然有些差错码功能很强,并且还能够纠错,但实际上由于开销太大以至于无法处理网络链路上发生的比特错和成组差错。即使使用纠错码,某些差错因为过于严重仍需丢弃其对应差错帧,因此可靠的链路协议必须能以某种方式回复这些丢失的帧。
通常使用两种基本的机制——**确认(ackonwledegment)和超时(timeout)**的组合来实现差错帧的重传,这个策略叫做:自动请求重发(Automatic Repeat Request,简称ARQ)
- 确认:接收端发送确认信号ACK给发送端用以告知成功接收某一帧
- 超时:发送端长时间未收到确认信号,重传该原始帧给接收端
ARQ算法一:停止—等待
算法
stop-and-wait 算法是最简单的ARQ算法,发送方传输一帧后,在传输下一帧前等待接受方发来的确认信号。如果在规定时间内没有接收到确认信号,则发送方超时,重传原始帧。
三种情形
![image-20211024144456113](https://i-blog.csdnimg.cn/blog_migrate/df17a5d457c8d9a594852ca7f6c1b8a7.png)
![image-20211024144515274](https://gitee.com/Lrk612/md_picture2/raw/master/img/image-20211024144515274.png)
分析
在stop-and-wait 算法中,接受方的确认信号如果丢失或者迟到了,那么如上面后两种情形一样,发送方会超时并重传原始帧,而接受方却会误以为收到的是下一帧。解决此问题的方法可以是给发送帧添加一个1比特的首部表示其序号,每一帧的序号在0、1间交替使用。
stop-and-wait 算法的主要缺点是链路资源浪费。它允许发送方每次在链路上只有一个未确定帧,这可能远远低于链路容量。
ARQ算法二:滑动窗口
考虑到stop-and-wait 算法的缺点,滑动窗口算法允许链路上同时传输的帧数达到链路的容量上限,也就是说滑动窗口算法的发送端在接收到确认信号前可以发送不止一帧数据后才进入等待。
算法
发送方
发送方对每一帧赋予一个序号,记为SeqNum,并维护三个变量:
- LFS:最近发送的帧(last frame sent),即还未确认成功发送的帧中序号最大者
- LAR:最近收到的确认帧(last ackoneledgement received),即已确认成功发送的帧中序号最大者
- SWS:发送窗口大小(send window size),即链路容量允许的同时发送帧数上限
发送窗口的大小是根据一段时间内链路上有多少待传输的帧来选择的,可根据给定延迟带宽积和帧的大小来计算得到。
当确认到达时,发送方向右移动LAR,从而允许发送方发送另一帧。同时发送方为所发送的每个帧设置一个定时器用于检测是否超时重传,因此发送方必须缓存SWS个帧。
接收方
接受方记录SeqNumToAck为当前已收到的连续序号帧中未回复ACK的最大序号,并维护三个变量:
- LAF:最大的可接收帧序号(largest accpetable frame)
- LFR:最后收到的帧序号(last frame received),是已经发送过ACK的帧中最大序号
- RWS:接收窗口的大小(receive window size),即接受方所能接收的无序帧数上限
接收窗口RWS的大小可以设置为任意值,但通常有两种:
- RWS=1,表示接收方不缓存任何错序到达的帧
- RWS=SWS,表示接收方能够缓存发送方传输的任何帧
当有新的数据帧发来时,接收方先做两种处理:
- 若帧序号 < LFR 或 帧序号 > LAF,则丢弃
- 若 LFR < 帧序号 < LAF,则接收
接受了新帧后,SeqNumToAck对应移动,但应明确一点:SeqNumToAck代表着接收到的连续序号的帧中序号最大者。如果序号不连续(序号低的帧有延迟或者丢失并待重传),则SeqNumToAck暂时不会变化。
一但当SeqNumToAck变化之后,接受方回传一个SeqNumToAck对应帧的ACK信号(而不是前面所有帧的),并赋值:LFR = SeqNumToAck,LAF = LFR + RWS。
例如
LFR=5(即上次接受方发送的ACK是确认5号帧),并且RWS=4,意味着LFR=9。若7、8号帧到达,则被存入缓冲区,但SeqNumToAck不会变化,因为6号帧还没到达。称7和8号帧是错序到达的。如果随后6号帧到达了(延迟或者丢失后重传来的),SeqNumToAck从5变成8,接收方回传8号帧的ACK信号;如果6号帧一直不来,则出现发送方超时,引发重传。
分析
在上例中可以看到,当发生超时时,窗口的滑动就会停滞,传输数据量减少。这意味着当分组丢失时,此方案不再保证管道满载,且分组丢失时间越长,这个问题越严重。
同时在上例中,可以不只是确认按顺序收到的最高序号的帧SeqNumToAck。就是说接收方在收到7、8号帧但是没有6号帧时,不管SeqNumToAck有没有变化,直接回传7、8号帧的ACK信号来确认二者的接收,这样能保证管道满载,但是增加了实现的复杂性,这个机制叫做选择确认。
序号的范围
由于帧首部的序号字段长度有限,不可能序号上限无穷大,因此帧的序号必须循环使用,这就带来了一个问题:要保证同一时刻链路上一个序号唯一确认一个帧,要求可用序号数必须大于所允许的待确认帧的数量。例如上面stop-and-wait算法中允许一次有一个待确认帧,并有两个不同序号。
对不同RWS,序号空间有不同要求:
- RWS=1,则 MaxSeqNum >= SWS + 1,即比发送窗口大小大1
- RWS=SWS,则 MaxSeqNum >= 2 * SWS - 1,即发送窗口大小不能大于可用序号数的一半
例如,有8个序号0~8,且RWS=SWS=7。假设发送方传输帧0~6,并且接收方成功接收,但是ACK丢失发送方没收到,那么接收方期待收到帧7和下一轮的帧0~5,但是发送方因为没收到ACK所以超时重传本轮的帧0~6,也就是说此时必须把(本轮的0~6帧) 和 (帧7+下轮0~5帧)通过序号区分开来,否则就会误识别。而这就要求序号必须要多于发送窗口大小的二倍。
点到点传输
上面算法建立在“帧在传输过程过程中不重新排序”的假设基础上,也就是点到点链路。如果是不同环境中的滑动窗口算法则需要设计其他规则。