c语言goout函数,Go Back N C语言实现(无ACK)

#include

#include

#include "protocol.h"

#include "datalink.h"

#define MAX_SEQ 6

#define DATA_TIMER 2600

#define inc(k) if(k

typedef struct//定义数据包packet

{

unsigned char data[PKT_LEN];

}packet;

typedef enum

{

true,false

} boolean ;

typedef unsigned int seq_nr ;

typedef struct//定义帧frame

{

unsigned char kind;// FRAME_DATA

unsigned char ack;

unsigned char seq;

unsigned char data[PKT_LEN];

unsigned int padding;

} frame ;

static int phylsical_ready = 0;//物理层是否准备好的标志,为1表示物理层已准备好,为0表示物理层没准备好.

seq_nr next_frame_to_send=0;

seq_nr ack_expected=0;

seq_nr frame_expected=0;

seq_nr nbuffered = 0;//正在用的缓存

frame f;

seq_nr i;

packet buffer[MAX_SEQ+1];

int event,arg,len;//事件,帧长度

static boolean between(seq_nr a, seq_nr b, seq_nr c)

{

return (( a<=b )&&( b

}

static void put_frame(unsigned char *frame, int len)//加入校验和

{

*(unsigned int *)(frame + len) = crc32(frame, len);

send_frame(frame, len + 4);

phylsical_ready = 0;

}

static void send_data(seq_nr frame_nr,seq_nr frame_expected,packet buffer[])

{

frame f;

f.kind = FRAME_DATA;//帧的类型

f.seq = frame_nr;//给帧加序号

f.ack = ( frame_expected + MAX_SEQ ) % ( MAX_SEQ + 1 ) ;//捎带确认

memcpy(f.data, buffer[frame_nr].data, PKT_LEN);//将buffer[frame_nr]中的数据拷贝到s.data中

dbg_frame("Send DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);

put_frame( (unsigned char *)&f, 3 + PKT_LEN ); //传输帧

start_timer(frame_nr, DATA_TIMER); //启动计时器

}

int main(int argc,char **argv)

{

protocol_init(argc, argv);

lprintf("Designed by nancyyihao, build: " __DATE__" "__TIME__"\n");

disable_network_layer();

while(1)

{

event = wait_for_event(&arg);

switch(event)

{

case NETWORK_LAYER_READY:

get_packet( buffer[next_frame_to_send].data );//收到一个新的packet

//lprintf("Send DATA %d\n",sizeof(buffer[next_frame_to_send].data)/ sizeof(buffer[next_frame_to_send].data[0]) );

nbuffered = nbuffered + 1 ;

send_data(next_frame_to_send, frame_expected,&buffer);

inc(next_frame_to_send);//发送者窗口前移(上限前移)

break;

case PHYSICAL_LAYER_READY:

phylsical_ready = 1;

break;

case FRAME_RECEIVED:

len = recv_frame((unsigned char *)&f, sizeof f);//从物理层取数据

if (len < 5 || (crc32((unsigned char *)&f, len) != 0))

{

dbg_event("**** Receiver Error, Bad CRC Checksum\n");

break;

}

if (f.kind == FRAME_DATA)

{

dbg_frame("Recv DATA %d %d, ID %d\n", f.seq, f.ack, *(short *)f.data);

//lprintf("Recv DATA %d\n",sizeof(f.data) / sizeof(f.data[0]));

if(f.seq == frame_expected)//收到了期待的帧

{

put_packet(f.data, len-7);//上交数据给网络层

inc(frame_expected);//接收方窗口前移(下限前移)

}

}

while(between(ack_expected, f.ack, next_frame_to_send))//处理捎带确认

{

nbuffered = nbuffered - 1 ;

stop_timer(ack_expected);//收到帧,计时器停止

inc(ack_expected);//缩小发送者窗口

}

break;

case DATA_TIMEOUT:

dbg_event("---- DATA %d timeout\n", arg) ;

next_frame_to_send = ack_expected ;//开始重传

for( i=1 ; i <= nbuffered ; i++ )

{

send_data(next_frame_to_send, frame_expected,&buffer);//重传

inc(next_frame_to_send);//准备下一个要传的dd帧

}

break;

}

if( ( nbuffered < MAX_SEQ ) && phylsical_ready )

enable_network_layer();

else

disable_network_layer();

}

}

有疑问加站长微信联系(非本文作者)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模仿数据链路层的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:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值