Data link layer:选择重传协议(A Protocol Using Selective Repeat)源码分析:protocol6.c

本文深入分析了《Computer Networks》一书中关于选择重传协议的实现代码protocal6.c,展示了前人在协议设计上的智慧和巧妙处理技巧。通读并理解这段代码有助于提升对选择重传协议的理解,同时能学习到协议实现的精华。
摘要由CSDN通过智能技术生成

不得不惊讶于前人的智慧和protocal6实现代码中大量巧妙地处理技巧。这部分代码是《Computer Networks, Andrew S.Tanenbaum (5th)》中对选择重传协议的实现代码的描述,其中充斥了大量可供学习、聪明的处理方法。能从头到尾彻彻底底地分析代码的实现机制,不仅有利于提高对protocol6的理解,还能很好地学习到前人设计协议、实现协议的智慧。

/* Protocol 6 (Selective repeat) accepts frames out of order but passes packets to the
network layer in order. Associated with each outstanding frame is a timer. When the timer
expires, only that frame is retransmitted, not all the outstanding frames, as in protocol 5. */

/* Sender and receiver are the same */


/*	关键细节
*	
*	1.data,nak都可以携带ack,且每次发送data nak都会携带一个ack,这就意味着会发送重复确认
*	
*	2.receiver收到frame_expected对应的data_frame后,先前移下沿窗口,再发ack(捎带确认)
*	故当发送捎带确认时,ack的序列号总是当前frame_expected的前一个序列号
*
*	3.ATTENTION!!!!!
*	双方是等价的,都各有一个发送窗口和接收窗口,所以双方既是sender也是receiver
*	代码中的sender和receiver都是相对于本方而言
*
*	4.buffer大小
*	(MAX_SEQ+1)>>1 
*
*	5.序列号在buffer内定位
*	frame_nr % NR_BUFS
*
*	6.ack序列号为frame_expected的上一个序列号
*	(frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
*
*	7.请求sender重传的data frame的序列号=frame_expected, 6中得到的ack序列号的下一个
*	(r.ack+1)%(MAX_SEQ+1)
*/

#define MAX_SEQ 7 /* should be 2ˆn − 1 */
#define NR_BUFS ((MAX_SEQ + 1)/2) //4
typedef enum {
   frame_arrival, cksum_err, timeout, network_layer_ready, ack_timeout} event_type;
#include "protocol.h"

boolean no nak = true; /* no nak has been sent yet */
seq_nr oldest_frame = MAX_SEQ + 1; /* initial value is only for the simulator */
//8

/*	
*	-:表示该区间是窗口区间
*	[0...a---b---c...7,0]:(a <= b) && (b < c)
*	[0---b---c...a---0]:(b < c) && (c < a)
*	[0---c...a---b---0]:(c < a) && (a <= b)
*/
//[a,c) 前闭后开区间 常用区间表示 STL常见到此类区间表示方法

static boolean between(seq_nr a, seq_nr b, seq_nr c)//已经有前提保证b>0
{
   
/* Same as between in protocol 5, but shorter and more obscure. */
	return ((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a));
}

/*
*	frame_expected对所有种类的frame一视同仁,都是当前本方receiver窗口下沿对应的窗口
*	接收方的frame_expected理论上的确不应该被其它任何值的改变所影响
*	
*	frame_kind=data, 则frame_nr=data frame的序列号,frame_expected是用于计算获取s.ack(frame_expected的上一个=s.ack)
*	第四个参数是out_buf	
*	
*	s.fk=data, s.seq=frame_nr, s.ack, s.info
*	
*	frame_kind=nak, 则frame_nr无效(默认为0), frame_expected用于计算s.ack, buffer为out_buf。
*	s.fk=nak, s.seq=0, s.ack, s.info
*	注意:此时的s.ack既有帮助处理nak也有捎带确认的功能(双重功效)
*	
*	发送nak的条件:nak尚未发出,此时receiver收到的data frame != frame_expected(窗口下沿)或checksum错误
*	接收处理nak的语句只有一个,即对上述两种需要发送nak的情况都用一块语句来接收处理。
*	
*	情况1:receiver收到的data frame != frame_expected(窗口下沿)
*	处理办法:假定对方sender窗口是[0 1 2],本方receiver窗口是[0 1 2],若对方sender发送0,本方sender回送的ack丢失,
*			但此时本方receiver窗口已经是[1 2 3],对方会重发0,此时触发本方sender发送nak的情况1。nak的唯一实用参数是
*			本方frame_expected,在send_frame()中,s.ack=本方frame_expected的上一个,
*			在对方接受处理nak的语句中 if(r.kind==nak),(r.ack+1)%(MAX_SEQ+1)=本方frame_expected=1
*	
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值