选择重传协议 C语言实现
来源:互联网 发布:windows设置ntp客户端 编辑:程序博客网 时间:2024/06/06 13:01
代码如下:
#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=0typedef enum{false,true}bool;typedef unsigned char seq_nr;//sequence or ack numbertypedef struct{unsigned char info[PKT_LEN];}packet;//packet definitionstatic 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 crcstatic 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 layerstatic 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 ackif(fk == FRAME_DATA)memcpy(s.data.info, buffer[frame_nr%NR_BUFS].info, PKT_LEN);//insert packet into frameif(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 frameif(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(); }}
0 0
- 选择重传协议 C语言实现
- 选择排序C语言实现
- 选择排序C语言实现
- 选择排序C语言实现
- 选择排序--c语言实现
- 选择排序C语言实现
- 选择排序(C语言实现)
- C语言实现选择排序
- c语言实现选择排序
- 选择排序c语言实现
- 传输层: 选择重传协议
- 可靠数据传输协议之选择重传
- 回退N帧协议与选择重传协议
- 数组去重(c语言实现)
- 字符串去重C语言实现
- TCP 滑动窗口协议/1比特滑动窗口协议/后退n协议/选择重传协议
- TCP 滑动窗口协议/1比特滑动窗口协议/后退n协议/选择重传协议
- 选择排序算法的C语言实现
- mac 下杀死一个端口号对应的进程
- .net micro framework的入门例程-点灯神话-7.队列存储LED灯闪烁时间并用串口发送
- epoll的原理和用法
- PIL模块与随机生成中文验证码
- 程序中使用cocostudio移植到android手机需要的若干配置过程
- 选择重传协议 C语言实现
- 发布或重启线上服务时抖动问题解决方案
- 最快速的Android开发环境搭建ADT-Bundle及Hello World
- 微软游戏设备2o14-9月进入中国内地市场
- 写了一个二叉树构造及中序遍历函数
- .net micro framework的入门例程-点灯神话-8.串口接收字符D即发送LED闪烁日志
- myEclipse/Eclipse 自动提示代码?呵呵,来吧!我告诉你
- 八皇后 入门经典
- [POJ 2887] Big String [块状链表]