版权声明:转载请附上文章地址 https://blog.csdn.net/weixin_38134491/article/details/84799926
为了提高传输的效率(填满管道),在等待确认时必须传输多个帧,这节讲的协议就能达到我们要的目的。
这个协议中,在接收到确认之前能发送几个帧,在确认到达之前我们会保存这些帧的副本。
序列号
我们要让每个帧的头部中包含序列号,如果一个真的头部允许序列号有m位,序列号的范围就是 2^m -1,
如果m=4,序列号范围是0-15,序列号可以重复
在Go-Back-N 协议中,序列号是模2^m, 这里m是以位为单位的序列号字段长度
滑动窗口 (sliding window)
Sliding window用来定义发送方和接收方关系的序列号范围
- 发送方关系的序列号范围叫 发送滑动窗口 Send sliding window
- 接收滑动窗口 receive sliding window
发送窗口是一个抽象概念,通过三个变量Sf,Sn, Ssize定义的一个大小为 2^m -1的假想盒子.
有效确认到达时,发送窗口能滑动一个或多个时隙。
接收窗口是一个抽象概念,通过唯一变量Rn定义了一个大小为1的假想盒子,当一个正确的帧到达后,窗口滑动,
但每次只滑动一个时隙。
定时器
虽然每个已发送的帧都能有一个定时器,但在我们的协议中我们只有一个,原因是第一个处理帧的定时器总是先到时,当这个定时器到时时,我们发送所有的待处理帧
确认
重发帧
设计
发送窗口大小
在Go-back-N Aotomatic Repeat Reauqest帧自动重发请求协议中,发送窗口的大小必须小于2^m,而接收窗口的大小始终是1
Sw=2^m -1;
Sf=0;
Sn=0;
while(true){ //不断重复
WaitForEvent();
if(Event(RequestToSend)){ //发送包
if(Sn-Sf>=Sw) //如果窗口满
sleep();
GetData();
MakeFrame(Sn);
StoreFrame(Sn);
SendFrame(Sn);
Sn=Sn+1;
if(timer not running)
StartTimer();
}
if(Event(ArrivalNotification)){ //ACK帧到达
Receive(ACK);
if(corrupted(ACK))
Sleep();
if((ackNo>Sf)&&(ackNo<=Sn))
while(Sf<=ackNo){
PurgeFrame(Sf);
Sf=Sf+1;
}
StopTimer();
}
if(Event(TimeOut)){ //计时器超时
StartTimer();
Temp=Sf;
while(Temp<Sn){
SendFrame(Sf);
Sf=Sf+1;
}
}
}
Go-back-N Automatic Repeat Request 接收方算法
Rn=0;
while(true){ //不断重复
WaitForEvent();
if(Event(ArrivalNotification)){ //数据帧到达
Receive(Frame);
if(corrupted(Frame))
sleep();
if(seqNo==Rn){ //如果为期望帧
DeliverData(); //传送数据
Rn=Rn+1; //滑动窗口
SendACK(Rn);
}
}
}