收藏 分销(赏)

CBN协议实现(c语言).doc

上传人:仙人****88 文档编号:9280585 上传时间:2025-03-19 格式:DOC 页数:24 大小:205KB 下载积分:10 金币
下载 相关 举报
CBN协议实现(c语言).doc_第1页
第1页 / 共24页
CBN协议实现(c语言).doc_第2页
第2页 / 共24页


点击查看更多>>
资源描述
中文注释 编程实现一个GBN传输协议的发送方和接收方两程序,采用编程语言不限,要求能将发送――接收流程以及处理方法表现出来. 附源代码及注释 源代码: 三:GBN-CS.c #include "GBN.h" #include <stdio.h> #include <string.h> #include <stdlib.h> extern int TRACE ; /* 用于跟踪 */ extern int nsim ; /* 当前第5层到第4层的信息数 */ extern int nsimmax; /*"msg"生成数量,直到停止,生成的最大信息数 */ extern float time; //时间 extern int packet_correct; //包的正确到达数 extern int packet_resent; //包的重传数 extern struct event *evlist; //事件 int main() //主函数 { struct event *eventptr;//变量,结构体声明 struct msg msg2give; struct pkt pkt2give; int i,j; char c; init();//初始化 A_init();//A端初始化 B_init();//B端初始化 while (1) //循环,用于每个包的传送 { eventptr = evlist; /* 从模拟器得到下一个事件 */ if (eventptr==NULL) goto terminate; evlist = evlist->next; /* 从事件清单改变该事件 */ if (evlist!=NULL) evlist->prev=NULL; if (TRACE >= 2)//打印与事件相关的信息 { printf("\n事件时间: %f,",eventptr->evtime); printf(" 类型: %d",eventptr->evtype); if (eventptr->evtype==0) printf(", 计时器中断: "); else if (eventptr->evtype==1) printf(", 来自第五层 "); else printf(", 来自第三层 "); if (eventptr->eventity == A)//打印事件实体 { printf(" 通信实体: %d A端\n",eventptr->eventity); } else { printf(" 通信实体: %d B端\n",eventptr->eventity); } } time = eventptr->evtime; /* 更新下一个事件的时间 */ if (nsim==nsimmax) break; /* 当输入包个数等于生成的最大包个数,模拟器停止 */ if (eventptr->evtype == FROM_LAYER5 ) //如果事件调用来自第五层 { generate_next_arrival(); /* 为将来的包的到达做准备 */ /* 将相同的信息转换为字母字符串 */ j = nsim % 26; for (i=0; i<20; i++) msg2give.data[i] = 97 + j; if (TRACE>2) { printf(" 学生发送的主要数据是: "); for (i=0; i<20; i++) printf("%c", msg2give.data[i]);//打印信息 printf("\n"); } nsim++; if (eventptr->eventity == A)//A端向外发送数据 { A_output(msg2give); } else//B端向外发送数据 { B_output(msg2give); } } else if (eventptr->evtype == FROM_LAYER3)//如果事件调用来自第三层 { pkt2give.seqnum = eventptr->pktptr->seqnum; pkt2give.acknum = eventptr->pktptr->acknum; pkt2give.checksum = eventptr->pktptr->checksum; for (i=0; i<20; i++) pkt2give.payload[i] = eventptr->pktptr->payload[i]; if (eventptr->eventity == A) /* A端交付包*/ A_input(pkt2give); /* 适当的实体*/ else /* B端交付包*/ B_input(pkt2give); free(eventptr->pktptr); /* 释放包的缓存 */ } else if (eventptr->evtype == TIMER_INTERRUPT)//计时器中断情况 { if (eventptr->eventity == A) A_timerinterrupt(); else B_timerinterrupt(); } else //校检,防止发生不可预料事件 { printf("内部警告: 不可预知的事件类型!! \n"); } free(eventptr); } terminate://终止 printf(" 模拟器停止在: %f s \n ,从第五层发送了 %d个包\n",time,nsim); printf(" 正确发送包的个数: %d \n", packet_correct); printf(" 重发包的个数: %d \n", packet_resent); system("pause");//暂停 } 一.GBN.h #pragma once #include <stdio.h> //基础功能模块的数据结构声明 #define BIDIRECTIONAL 1 /* 改变值1如果你需要写额外的可靠程序或B输出 程序(即B端系统)*/ /* "msg"结构体是由第五层(教师代码)转变成第四层的数据单元(学生代码) */ /*它包括了经由第五层向学生层协议通信实体交付的数据(字符)*/ struct msg { char data[20]; }; /* "pkt"结构体是第4层(学生代码)向第3层传送的数据单元(老师代码)。值 得注意的是预先定义的包结构,这一切学生必须遵守。*/ struct pkt { int seqnum;//顺序号 int acknum;//应答号 int checksum;//检查和 char payload[20]; }; #define WINDOWSIZE 8 //定义滑动窗口大小 #define MAXBUFSIZE 50//最大窗口大小 #define RTT 15.0//周游时间 #define NOTUSED 0//没用到 #define NACK -1//否定应答 #define TRUE 1 #define FALSE 0 #define A 0 #define B 1 //网络仿真部分数据结构声明 *********************************************************** struct event { float evtime; /* 事件时间 */ int evtype; /* 事件类型 */ int eventity; /* 事件实体*/ struct pkt *pktptr; /* 指向这个事件的指针(如果需要) */ struct event *prev; //前一事件 struct event *next; //后一事件 }; /* possible events: */ #define TIMER_INTERRUPT 0 //事件中断 #define FROM_LAYER5 1 //来自第五层 #define FROM_LAYER3 2 //来自第三层 #define OFF 0 #define ON 1 //基础功能模块的函数声明 ******************************************************************* void ComputeChecksum(struct pkt *packet);//计算校验和 int CheckCorrupted(struct pkt packet);//检查数据是否出错 void A_output( struct msg message);//A端向外发送数据 void A_input(struct pkt packet);//A端接收数据 void A_timerinterrupt();//A计时器超时 void A_init();//A端初始化 void B_output(struct msg message); void B_input(struct pkt packet); void B_timerinterrupt(); void B_init(); //网络仿真部分的函数声明 ************************************************** void init(); //初始化仿真器 float jimsrand();//随机数发生器[0,1] //处理事件列表部分的函数声明 ********************************************* void generate_next_arrival();//产生下一个到达的分组 void insertevent(struct event *p);//向事件列表中插入一条新的事件 void printevlist();//打印事件列表 //******************************************************************** //**********************计时器模块*********************************** void stoptimer(int);//停止计时器 void starttimer(int,float);//启动计时器 //********************************************************************* //**************************网络各层之间传送模块*********************** void tolayer3(int AorB,struct pkt packet);//向第3层发送信息 void tolayer5(int AorB,char datasent[20]);//向第5层发送信息 二: #include "GBN.h" #include <stdio.h> #include <string.h> #include <stdlib.h> extern int TRACE = 1; /* 用于跟踪*/ extern int nsim = 0; /* 当前第5层到第4层的信息数*/ extern int nsimmax = 0; /* "msg"生成数量,直到停止*/ extern float time = 0.000; float lossprob; /* 丢包可能性*/ float corruptprob; /* 包的数据位数丢失可能性*/ float lambda; /* 从第五层到达的比率 */ int ntolayer3; /* 送往第3层的包数量*/ static int nlost = 0; /* 在媒体中丢失的包数量*/ static int ncorrupt = 0; /* 在网络中被破坏的包*/ static int expectedseqnum = 0; /* 期待接收方发送的序号 */ static int nextseqnum; /* 下一次发送方要使用的包序号*/ static int base; /* 发送方头窗*/ struct pkt winbuf[WINDOWSIZE]; /* 窗口包缓冲区*/ static int winfront,winrear; /* 缓冲区的头尾指针*/ static int pktnum; /* 缓冲窗口包的数量*/ struct msg buffer[MAXBUFSIZE]; /* 发送方数据缓冲区*/ int buffront,bufrear; /* 缓冲区的头尾指针 */ static int msgnum; /* 缓冲窗口包的数量 */ //关于各种包的类型定义 //*********************************************************** int packet_lost =0; //包丢失 int packet_corrupt=0; //包破坏 int packet_sent =0; //包发送 extern int packet_correct=0;//正确包 extern int packet_resent =0;//重发包 int packet_timeout=0;//超时包 extern struct event *evlist = NULL; /* 事件清单 */ //相关接口函数的实现 //计算校验和,即脚链和1的补码和 void ComputeChecksum( struct pkt *packet) { int checksum; int i; checksum = packet->seqnum; checksum = checksum + packet->acknum;//求脚链 for ( i=0; i<20; i++ ) //取最高位,按位相加 checksum = checksum + (int)(packet->payload[i]); checksum = 0-checksum;//取反 packet->checksum = checksum; } //检查是否出错 int CheckCorrupted(struct pkt packet) { int checksum; int i; checksum = packet.seqnum; checksum = checksum + packet.acknum; for ( i=0; i<20; i++ ) checksum = checksum + (int)(packet.payload[i]); if ( (packet.checksum+checksum) == 0 )//检查校检和是否相加为0 return (FALSE); else return (TRUE); } //A端向外发送数据 /* 被第五层调用,向另一端发送数据*/ void A_output(struct msg message) { int i; struct pkt sendpkt; /* 如果的发送方下次使用序号小于滑动窗口的最大序号,那么补发包*/ if ( nextseqnum < base+WINDOWSIZE ) { printf("----A:新的包到达,发送窗口不满,新的包送往第3层!\n"); /* 创建包 */ sendpkt.seqnum = nextseqnum; sendpkt.acknum = NOTUSED; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = message.data[i]; /* 检查是否出错 */ ComputeChecksum (&sendpkt); /* 送出包 */ tolayer3 (A, sendpkt); /* 复制这些包到窗口缓冲区 */ winrear = (winrear+1)%WINDOWSIZE; pktnum ++; winbuf[winrear] = sendpkt; for (i=0; i<20; i++) winbuf[winrear].payload[i]= sendpkt.payload[i]; /* 更新状态变量 */ nextseqnum = nextseqnum+1; starttimer(A,RTT); B_input(sendpkt); A_input(sendpkt); } /* 如果移动窗口包满*/ else { printf("----A:新的包到达,发送窗口已满!"); /* 如果缓冲区满,放弃并退出*/ if ( msgnum == MAXBUFSIZE) { printf (" 错误:发送缓冲区已满 !!!\n"); exit (1); } /* 否则,将信息送入缓冲区 */ else { printf("信息已送入缓冲区\n"); bufrear = (bufrear+1) % MAXBUFSIZE; //拥塞控制,防止拥塞,减小缓冲区 for (i=0; i<20; i++) buffer[bufrear].data[i] = message.data[i]; msgnum ++; } } } //B端向外发送数据 /* 被第五层调用,发送数据到另一方,同A方相似 */ void B_output(struct msg message) { int i; struct pkt sendpkt; /* 如果发送窗口不满*/ if ( nextseqnum < base+WINDOWSIZE ) { printf("----B:新的包到达,发送窗口不满,新的包送往第3层!!\n"); /* create packet */ sendpkt.seqnum = nextseqnum; sendpkt.acknum = NOTUSED; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = message.data[i]; /* computer checksum */ ComputeChecksum (&sendpkt); /* send out packet */ tolayer3 (A, sendpkt); A_input(sendpkt); /* copy the packet to window packet buffer */ winrear = (winrear+1)%WINDOWSIZE; pktnum ++; winbuf[winrear] = sendpkt; for (i=0; i<20; i++) winbuf[winrear].payload[i]= sendpkt.payload[i]; /* if it is the first packet in window, start timeout */ //if ( base == nextseqnum ) //{ //starttimer(A,RTT); //printf("----A: start a new timer!\n"); // } /* update state variables */ nextseqnum = nextseqnum+1; } /* 如果发送窗口满*/ else { printf("----B:新的包到达,发送窗口已满!,"); /* if buffer full, give up and exit*/ if ( msgnum == MAXBUFSIZE) { printf (" 错误:发送缓冲区已满 ! \n"); exit (1); } /* otherwise, buffer the message */ else { printf("缓冲区满!\n"); bufrear = (bufrear+1) % MAXBUFSIZE; for (i=0; i<20; i++) buffer[bufrear].data[i] = message.data[i]; msgnum ++; } } } //A端接收数据 void A_input(struct pkt packet) { struct pkt sendpkt; int i; /* 如果收到没有被破坏的包并且确认包收到*/ if ( (CheckCorrupted(packet) == FALSE) && (packet.acknum != NACK) ) { printf("----A: ACK(确认包) %d 被正确的收到,",packet.acknum); packet_correct++; /* 从窗口缓冲区删去被确认的包*/ winfront = (winfront+(packet.acknum+1-base)) % WINDOWSIZE; pktnum = pktnum - (packet.acknum+1-base); /* 改变窗口最小号确认包 */ base = packet.acknum+1; stoptimer(A); if ( base < nextseqnum) { //starttimer(A,RTT); printf ("\n\n\n发送新的包!"); } /* 如果缓冲区不空发送新的包*/ while ( (msgnum!=0) && (nextseqnum<base+WINDOWSIZE) ) { /* 创建包*/ sendpkt.seqnum = nextseqnum; sendpkt.acknum = NOTUSED; buffront = (buffront+1) % MAXBUFSIZE; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = buffer[buffront].data[i]; /* 和确认*/ ComputeChecksum (&sendpkt); /*如果是滑动窗口的第一个包,开始超时检测*/ if ( base == nextseqnum ) //如果滑动窗口最小的包等于下一次要发送的序号 { //starttimer(A,RTT); printf ("发送新的包!\n"); } /* 送出包 */ tolayer3 (A, sendpkt); /* 复制包到窗口缓冲区 */ winrear = (winrear+1)%WINDOWSIZE; winbuf[winrear] = sendpkt; pktnum ++; /* 更新状态变量 */ nextseqnum = nextseqnum+1; /* 删除缓冲区的包 */ msgnum --; } } else printf ("----A: 收到否定应答,什么也没有完成!\n"); } //B端接收数据*****************************************************一定要调用这个 /* 这只是单一的A到B的传送方式,没有B端的数据发出 */ /* 被第三层调用,但数据到达B端第4层*/ void B_input(struct pkt packet) { struct pkt sendpkt; int i; /*如果收到没有被破坏的包并且确认包收到 */ if ( (CheckCorrupted(packet) == FALSE) && (packet.seqnum == expectedseqnum)) { printf("\n----B: 包正确的到达,发送ACK确认包\n",packet.seqnum); /* 发送应答包 */ /* create packet */ sendpkt.seqnum = NOTUSED; sendpkt.acknum = expectedseqnum; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = '0'; /* computer checksum */ ComputeChecksum (&sendpkt); /* send out packet */ //tolayer3 (B, sendpkt); /* update state variables */ expectedseqnum = expectedseqnum+1; printf("----B:expectedseqnum (期待下一次的发送序号)= %d\n",expectedseqnum); /* 发送包到第五层 */ //tolayer5(B,packet.payload); } /* 否则,抛弃包,发送否定应答*/ else { printf("----B: 包 %d 损坏或者不是我所需要的, 发送否定应答!\n",packet.seqnum); /* 创建包 */ sendpkt.seqnum = NOTUSED; sendpkt.acknum = NACK; for ( i=0; i<20 ; i++ ) sendpkt.payload[i] = '0'; /* 校检和检查 */ ComputeChecksum (&sendpkt); /* 发出包 */ tolayer3 (B, sendpkt); } } //A计时器超时 /* A超时被调用 */ void A_timerinterrupt() { int i; printf("----A:超时!!!重新发包!\n"); /* start timer */ starttimer(A,RTT); /* 重新发送所有未被确认的包*/ for ( i=1; i<=pktnum; i++ ) { packet_resent++; tolayer3(A,winbuf[(winfront+i)%WINDOWSIZE]); } } //B计时器超时 /* called when B's timer goes off */ void B_timerinterrupt() { int i; printf("----B: 超时!!!重新发包!\n"); /* start timer */ starttimer(B,RTT); /* 重新发送所有未被确认的包 */ for ( i=1; i<=pktnum; i++ ) { packet_resent++; tolayer3(B,winbuf[(winfront+i)%WINDOWSIZE]); } } //A端初始化 /* entity A routines are called. You can use it to do any initialization */ void A_init() { base = 0; nextseqnum = 0; buffront = 0; bufrear = 0; msgnum = 0; winfront = 0; winrear = 0; pktnum = 0; } //B端初始化 /* entity B routines are called. You can use it to do any initialization */ void B_init() { expectedseqnum = 0; } //初始化仿真器 void init() /* initialize the simulator */ { int i; float sum, avg; float jimsrand(); FILE *fp; fp = fopen ("parameter.txt","r"); printf("----- Stop and Wait Network Simulator Version 1.1 -------- \n\n"); printf(" -----停止等待网络模拟器版本1.1 -------- \n\n"); printf("回车输入包的个数给虚拟器: "); //fscanf(fp,"%d",&nsimmax); scanf("%d",&nsimmax); printf("\n输入包被丢失的可能性[输入 0.0 表示不丢失]: "); //fscanf(fp, "%f",&lossprob); scanf("%f",&lossprob); printf("\n输入包被损坏的可能性[输入 0.0 表示不损坏]:"); //fscanf(fp,"%f",&corruptprob); scanf("%f",&corruptprob); printf("\n输入包从发送方第五层到达的平均时间[ > 0.0]: "); //fscanf(fp,"%f",&lambda); scanf("%f",&lambda); printf("\n输入跟踪: "); //fscanf(f
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服