CBN协议实现(c语言).doc_第1页
CBN协议实现(c语言).doc_第2页
CBN协议实现(c语言).doc_第3页
CBN协议实现(c语言).doc_第4页
CBN协议实现(c语言).doc_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

中文注释编程实现一个GBN传输协议的发送方和接收方两程序,采用编程语言不限,要求能将发送接收流程以及处理方法表现出来.附源代码及注释源代码:三:GBN-CS.c#include GBN.h#include #include #include 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(, 来自第五层 );elseprintf(, 来自第三层 );if (eventptr-eventity = A)/打印事件实体printf( 通信实体: %d A端n,eventptr-eventity); elseprintf( 通信实体: %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; i2)printf( 学生发送的主要数据是: );for (i=0; ieventity = 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; ipktptr-payloadi;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();elseB_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 /基础功能模块的数据结构声明#define BIDIRECTIONAL 1 /* 改变值1如果你需要写额外的可靠程序或B输出程序(即B端系统)*/* msg结构体是由第五层(教师代码)转变成第四层的数据单元(学生代码)*/*它包括了经由第五层向学生层协议通信实体交付的数据(字符)*/struct msg char data20;/* pkt结构体是第4层(学生代码)向第3层传送的数据单元(老师代码)。值得注意的是预先定义的包结构,这一切学生必须遵守。*/struct pktint seqnum;/顺序号int acknum;/应答号int checksum;/检查和char payload20;#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 eventfloat 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 datasent20);/向第5层发送信息二:#include GBN.h#include #include #include 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 winbufWINDOWSIZE; /* 窗口包缓冲区*/static int winfront,winrear; /* 缓冲区的头尾指针*/static int pktnum;/* 缓冲窗口包的数量*/struct msg bufferMAXBUFSIZE; /* 发送方数据缓冲区*/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; ipayloadi);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; i20; i+ ) checksum = checksum + (int)(packet.payloadi);if ( (packet.checksum+checksum) = 0 )/检查校检和是否相加为0return (FALSE);elsereturn (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; i20 ; i+ ) sendpkt.payloadi = message.datai;/* 检查是否出错 */ComputeChecksum (&sendpkt); /* 送出包 */ tolayer3 (A, sendpkt); /* 复制这些包到窗口缓冲区 */ winrear = (winrear+1)%WINDOWSIZE; pktnum +; winbufwinrear = sendpkt; for (i=0; i20; i+) winbufwinrear.payloadi= sendpkt.payloadi; /* 更新状态变量 */ 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; i20; i+) bufferbufrear.datai = message.datai; 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; i20 ; i+ ) sendpkt.payloadi = message.datai;/* 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 +; winbufwinrear = sendpkt; for (i=0; i20; i+) winbufwinrear.payloadi= sendpkt.payloadi; /* 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; i20; i+) bufferbufrear.datai = message.datai; 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 (nnn发送新的包!); /* 如果缓冲区不空发送新的包*/ while ( (msgnum!=0) & (nextseqnumbase+WINDOWSIZE) )/* 创建包*/ sendpkt.seqnum = nextseqnum; sendpkt.acknum = NOTUSED; buffront = (buffront+1) % MAXBUFSIZE; for ( i=0; i20 ; i+ ) sendpkt.payloadi = bufferbuffront.datai; /* 和确认*/ ComputeChecksum (&sendpkt); /*如果是滑动窗口的第一个包,开始超时检测*/ if ( base = nextseqnum ) /如果滑动窗口最小的包等于下一次要发送的序号/starttimer(A,RTT);printf (发送新的包!n); /* 送出包 */ tolayer3 (A, sendpkt); /* 复制包到窗口缓冲区 */ winrear = (winrear+1)%WINDOWSIZE; winbufwinrear = 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; i20 ; i+ )sendpkt.payloadi = 0; /* computer checksum */ ComputeChecksum (&sendpkt); /* send out packet */tolayer3 (B, sendpkt);/* update state variables */expectedseqnum = expectedseqnum+1; printf(-B:expectedseqnum (期待下一次的发送序号)= %dn,expectedseqnum); /* 发送包到第五层 */ /tolayer5(B,packet.payload); /* 否则,抛弃包,发送否定应答*/ elseprintf(-B: 包 %d 损坏或者不是我所需要的, 发送否定应答!n,packet.seqnum); /* 创建包 */ sendpkt.seqnum = NOTUSED; sendpkt.acknum = NACK; for ( i=0; i20 ; i+ ) sendpkt.payloadi = 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 Bs timer goes off */void B_timerinterrupt()int i;printf(-B: 超时!重新发包!n);/* start timer */starttimer(B,RTT);/* 重新发送所有未被确认的包 */for ( i=1; i 0.0: ); /fscanf(fp,%f,&lambda);scanf(%f,&lambda); printf(n输入跟踪: );/fscanf(fp,%d,&TRACE);scanf(%d,&TRACE);printf(nn);srand(9999); /* init random number generator */sum = 0.0; /* test random number generator for students */for (i=0; i1000; i+)sum=sum+jimsrand(); /* jimsrand() should be uniform in 0,1 */avg = sum/1000.0; /*if(avg 0.75) printf(It is likely that random number generation on your machinen ); printf(is different from what this emulator expects. Please taken); printf(a look at the routine jimsrand() in the emulator code. Sorry. n); exit(0); */ printf(%f,avg);ntolayer3 = 0;nlost = 0;ncorrupt = 0;time=0.0; /* initialize time to 0.0 */ generate_next_arrival(); /* initialize event list */随机数发生器float jimsrand() double mmm = 2147483647; /* largest int - MACHINE DEPENDENT! */float x; /* individual students may need to change mmm */ x = rand()/mmm; /* x should be uniform in 0,1 */return(x); /*/*事件处理部分*void generate_next_arrival()double x,log(),ceil();struct event *evptr;float ttime;int tempint;/if (TRACE2)/printf(-GENERATE NEXT ARRIVAL: creating new arrivaln);x = lambda*jimsrand()*2; /* x is uniform on 0,2*lambda */ /* having mean of lambda */evptr = (struct event *)malloc(sizeof(struct event);evptr-evtime = time + x; evptr-evtype = FROM_LAYER5;if (jimsrand()eventity = A;elseevptr-eventity = B;insertevent(evptr);/向事件列表中插入一条新的事件void insertevent(struct event *p) struct event *q,*qold;if (TRACE2)/printf( INSERTEVENT: time is %lfn,time);/printf( INSERTEVENT: future time will be %lfn,p-evtime); q = evlist; /* q points to front of list in which p struct inserted q指针指向表前部当p结构被插入*/if (q=NULL)/* 表是空的*/ evlist=p; p-next=NULL; p-prev=NULL; else for (qold = q; q !=NULL & p-evtime q-evtime; q=q-next)qold=q; if (q=NULL)/* 表尾 */ qold-next = p; p-prev = qold; p-next = NULL;else if (q=evlist)/* front of list */ p-next=evlist; p-prev=NULL; p-next-prev=p; evlist = p;else /* 表中部 */ p-next=q; p-prev=q-prev; q-prev-next=p; q-prev=p;/打印事件列表void printevlist()struct event *q;int i;printf(-n事件列表如下:n);for(q = evlist; q!=NULL; q=q-next)printf(事件时间: %f, 类型: %d 实体: %dn,q-evtime,q-evtype,q-eventity); printf(-n);/启动计时器void starttimer(int AorB,float increment)struct event *q;struct event *evptr;if (TRACE2)printf(n-A: 启动计时器: 在 %f 开始定时n,time);/* 友好的:检查计时器是否早已开始计时,如果是,则发出警告*/*

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论