选择重传协议 C语言实现

代码如下:
#include <stdio.h>
#include <string.h>

#include "protocol.h"
#include "datalink.h"

#define MAX_SEQ 31
#define DATA_TIMER 3800//calculagraph timer
#define ACK_TIMER 1100
#define NR_BUFS 16   //windows number
#define inc(k)if(k<MAX_SEQ)k++;else k=0

typedef enum{false,true}bool;
typedef unsigned char seq_nr;//sequence or ack number
typedef struct{
	unsigned char info[PKT_LEN];
}packet;//packet definition

static int phl_ready = 0;

bool no_nak=true;

typedef struct FRAME { 
    unsigned char kind; // FRAME_DATA 
    seq_nr ack;//acknowledgement number
    seq_nr  seq;//sequence number
    packet data; //the network layer packet
    unsigned int  padding;
}Frame;

static int between(seq_nr a,seq_nr b,seq_nr c){
      if((a <= b && b < c) || (c < a && a <= b) || (b < c && c < a))
          return true;
      else
          return false; 
}
//add crc
static void put_frame(unsigned char *frame, int len)
{
    *(unsigned int *)(frame + len) = crc32(frame, len);
    send_frame(frame, len + 4);
    phl_ready = 0;
}
//send data to physical layer
static void send_data(unsigned char fk,seq_nr frame_nr,seq_nr frame_expected,packet buffer[])
{
    Frame s;
    s.kind = fk;
    s.seq = frame_nr;//insert sequence number into frame
    s.ack = (frame_expected+ MAX_SEQ)%(MAX_SEQ+1);//piggyback ack

	if(fk == FRAME_DATA)
		memcpy(s.data.info, buffer[frame_nr%NR_BUFS].info, PKT_LEN);//insert packet into frame
	
	if(fk == FRAME_NAK)
		no_nak = false;  //one nak per frame,please

    dbg_frame("Send DATA %d %d, ID %d\n", s.seq, s.ack, *(short *)s.data.info);
	if (fk == FRAME_DATA)
     	put_frame((unsigned char *)&s, 3 + PKT_LEN);//put CRC following the frame	
	if(fk == FRAME_NAK||fk==FRAME_ACK)
		put_frame((unsigned char *)&s, 2);//put CRC following the frame
    if(fk == FRAME_DATA)
		start_timer(frame_nr%NR_BUFS, DATA_TIMER);
	stop_ack_timer();//no need for separate ack frame
}

int main(int argc, char **argv){
    
	int event,arg,len=0;
    int i;//contol the number of circle of arrived
    Frame r;//scratch variable
    seq_nr next_frame_to_send;//the upper of the send's window
    seq_nr ack_expected;//the lower of the send's window
    seq_nr frame_expected;//the lower of the reciver's window
    seq_nr too_far;//the upper of the reciver's window
    seq_nr nbuffered;//currently window
    packet out_buf[NR_BUFS];//buffer for the outbound stream
    packet in_buf[NR_BUFS];//buffer for the in stream
    bool arrived[NR_BUFS];
    
    enable_network_layer();
    //disable_network_layer();//allow netword_layer_ready events
    ack_expected = 0;
    next_frame_to_send = 0;
    frame_expected = 0;
    too_far = NR_BUFS;
    nbuffered = 0;  
    for(i = 0;i < NR_BUFS;i++)
        arrived[i] = false;

	protocol_init(argc, argv); 
    lprintf("Designed by chenchen_07415_071419, build: " __DATE__"  "__TIME__"\n\n");

    while(true){
        event = wait_for_event(&arg);
        switch(event){
            case NETWORK_LAYER_READY:
				   nbuffered++;//expand the sender's window
                   get_packet(out_buf[next_frame_to_send%NR_BUFS].info);//fetch new packet
                   send_data(FRAME_DATA,next_frame_to_send,frame_expected,out_buf);//transmit the packet
			       inc(next_frame_to_send);//advance the upper edge of sender's window
                   break;
            case PHYSICAL_LAYER_READY:
                 phl_ready = 1;
                 break;
            case FRAME_RECEIVED:
                 len = recv_frame((unsigned char *)&r, sizeof r);//from physical frame's len
                 if (len < 5 || crc32((unsigned char *)&r, len) !=0){//CRC error
                     dbg_event("**** Receiver Error, Bad CRC Checksum\n");
                     if(no_nak)
                         send_data(FRAME_NAK,0,frame_expected,out_buf);
                     break;
                 }
                 if(r.kind == FRAME_DATA){
                    if((r .seq != frame_expected)&&no_nak)//not arrival in the right order
                         send_data(FRAME_NAK,0,frame_expected,out_buf);//send nac and send again
                    else
                         start_ack_timer(ACK_TIMER);
                    if(between(frame_expected,r.seq,too_far)&&(arrived[r.seq%NR_BUFS]==false)){
                         arrived[r.seq%NR_BUFS] = true;//the frame arrival
					     //for(j=0;j<NR_BUFS;j++)
                          in_buf[r.seq%NR_BUFS] = r.data;//keep in the in_buf 
                         while(arrived[frame_expected%NR_BUFS]){
                             put_packet(in_buf[frame_expected%NR_BUFS].info, len-7);
                             no_nak = true;
                             arrived[frame_expected%NR_BUFS]=false;
                             inc(frame_expected);//advance upper edge of ceiver's windowsge
                             inc(too_far);
                             start_ack_timer(ACK_TIMER);
                         }  
                    }
                 }
                 if((r.kind == FRAME_NAK)&&between(ack_expected,(r.ack+1)%(MAX_SEQ+1),next_frame_to_send))
                 //receive nak &&between the windows 
                     send_data(FRAME_DATA,(r.ack+1)%(MAX_SEQ+1),frame_expected,out_buf);
                 while(between(ack_expected,r.ack,next_frame_to_send)){
                       nbuffered--;
                       stop_timer(ack_expected%NR_BUFS);
                       inc(ack_expected);
                 }
                 break;
            case ACK_TIMEOUT:
				 dbg_event("---- DATA %d timeout\n", arg);
                 send_data(FRAME_ACK,0,frame_expected,out_buf);
                 break;
            case DATA_TIMEOUT:
                 dbg_event("---- DATA %d timeout\n", arg); 
		         if(! between(ack_expected,arg,next_frame_to_send))
                    arg = arg + NR_BUFS;
                 send_data(FRAME_DATA,arg,frame_expected,out_buf);//select the bad frame and resend it 
                 break;
        }
        if (nbuffered <NR_BUFS&& phl_ready)
            enable_network_layer();
        else
            disable_network_layer();
    }
}            

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
模仿数据链路层的gobackn协议 /*该协议是搭载ack的回退n步协议*/ #include #include "protocol.h" #define max_seq 7 #define flag 126 #define ESC 100 #define wait_time 2700 //发送计时器等待的时间 #define ack_wait_time 280 static int phl_ready = 0; unsigned char buf[max_seq+1][270]; unsigned char ack[8]; //发送空的ack帧 unsigned char in_buf[600], last_buf[520];//接收时的缓冲区;去掉冗余之后的缓冲区,为防备因误码两帧合并为一帧而定义了很大一个数组 int nbuffered=0; //发送的帧数 int buf_size[max_seq+1]; //记下以发送各帧的帧长 int next_frame_to_send=0; int frame_in_phl=0; //用于成帧 int frame_expected=0; int ack_expected=0; int between(int a,int b,int c) { if( ((a<=b)&&(b<c)) || ((c<a)&&(a<=b)) || ((b<c)&&(c<a)) ) return 1; else return 0; } //判断帧尾,防止出现误判esc esc flag为数据的情况 int end_flag(int in_len) { int count=0; int i; if(in_len=0;i--)//记录flag前的esc数目 count++; return count%2; //若flag前的esc为偶数,则为帧尾 }//成帧函数--数据帧 void send_frame(char *my_buf,int len) { int n; buf[frame_in_phl][0]=(frame_expected+max_seq)%(max_seq+1); //ack buf[frame_in_phl][1]=frame_in_phl; //发送帧的帧号 for(n=0;n<len;n++) buf[frame_in_phl][n+2]=my_buf[n]; //将处理过的新帧赋值到缓冲区中 len=len+2; *(unsigned int *)(buf[frame_in_phl]+len) = crc32(buf[frame_in_phl],len); //在原始帧的基础上加检验和 buf_size[frame_in_phl]=len+4; //记录当前帧的长度,包括3个帧头,4个检验和 nbuffered=nbuffered+1; //缓冲区占用数加一 frame_in_phl=(frame_in_phl+1)%(max_seq+1); } //成帧函数--ack帧 void send_ack() //ack帧的处理 { ack[0]=(frame_expected+max_seq)%(max_seq+1); ack[1]=max_seq+10; //ack帧的序号位,使ack[1]==frame_expected恒不成立 *(unsigned int *)(ack+2) = crc32(ack,2); //在原始帧的基础上加检验和 } //主函数 int main(int argc, char **argv) { int event, arg, n , m , i , j , len = 0 ,in_len = 0; unsigned char my_buf[260]; int phl_wait=0; //在物理层中还没有被发送的帧 protocol_init(argc, argv); enable_network_layer(); for (;;) { event = wait_for_event(&arg); switch (event) { case NETWORK_LAYER_READY:
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值