课程设计报告-滑动窗口协议仿真_第1页
课程设计报告-滑动窗口协议仿真_第2页
课程设计报告-滑动窗口协议仿真_第3页
免费预览已结束,剩余30页可下载查看

下载本文档

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

文档简介

1、滁州学院课程设计报告课程名称:计算机网络设计题目:滑动窗口协议仿真系 别:计算机与信息工程学院专 业:计算机科学与技术组 别:第五组起止日期:2011年11月24日2011年12月7日指导教师:赵国柱计算机与信息工程学院二O一年制课程设计题目滑动窗口协议仿真组长赵育坤学号2011220135班级计专1班系别计算机与信息 工程学院专业计算机科学与技术组员闫婷、张侠、余静、于东锋、张飞、赵育坤指导教师赵国柱课程设计目的掌握滑动窗口协议的基本原理,并能够用所学计算机高级 语言进行编程模拟课程设计所需环境开发环境:VC+运行环境:Windows操作系统课程设计任务要求1 程序按照滑动窗口协议实现端对端

2、的数据传送。包括协议的各 种策略,如包丢失、停等应答、超时等都应有所仿真实现2显示数据传送过程中的各项具体数据。双方帧的个数变化,帧 序号,发送和接受速度,暂停或重传提示等课程设计工作进度计划序号起止日期工作内容分工情况111月24号11月27号了解工作要求,明确分工内 容,网上查阅相关资料所有组员共同参与211月28号11月30号sender队列模块的编写由闫婷完成312月1号12月4号sender主函数的编写由赵育坤、张飞完成411月28号11月30号receiver 队列模块的编写由张侠完成512月1号12月4号receiver 主函数的编写由余静、于东锋完成612月5号12月7号最后汇

3、总,调试由赵育坤、于东锋完成指导教师签字:年月日教研室审核意见:教研室主任签字:年月日课程设计任务书一 . 引言二. 基本原理2.1 窗口机制2.2 1bit 滑动窗口协议2.3 后退 N 协议2.4 选择重传协议2.5 流量控制三 . 需求分析3.1课程设计题目3.2开发环境3.3运行环境3.4课程设计任务及要求3.5界面要求3.6网络接口要求四. 详细设计4.1结构体的定义4.2发送方的主要函数4.3接受方的主要函数五. 源代码5.1发送方的主要代码5.2接收方的主要代码六 . 调试与操作说明致谢 参考文献 课程设计的主要内容1. 引言 早期的网络通信中,通信双方不会考虑网络的拥挤情况直接

4、发送数据。由于大家 不知道网络拥塞状况,一起发送数据,导致中间结点阻塞掉包,谁也发不了数据。在 数据传输过程中,我们总是希望数据传输的更快一些,但如果发送方把数据发送的过快, 接收方就可能来不及接收,这就造成数据的丢失。因此就有了滑动窗口机制来解决这些 问题。早期我们使用的是 1bit 滑动窗口协议,一次只发送一个帧,等收到 ack 确认 才发下一个帧,这样对信道的利用率太低了。因此提出了一种采用累积确认的连续 ARQ 协议,接收方不必对收到的帧逐个发送 ack 确认,而是收到几个帧后, 对按序到达的最后一 个帧发送 ack 确认。同 1bit 滑动窗口协议相比,大大减少了 ack 数量,并消

5、除了延迟 ack 对传输效率的影响。 但是,这会产生一个新的问题,如果发送方发送了 5 个帧,而中间的第 3 个帧丢失了。这时接收方只能对前2 个帧发出确认。发送方无法知道后面三个帧的下落,只好把后面的3个帧再重传一次,这就是回退N协议。为了解决这个问题,又提出了选择重传协议。 当接收方发现某帧出错后,继续接受后面送来的正确的帧,只是不交付它们, 存放在自己的缓冲区中, 并且要求发送方重传出错的那一帧。一旦收到重传来的帧后,就可以将存于缓冲区中的其余帧一并按正确的顺序递交给主机。2. 基本原理2.1 窗口机制滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的 帧的序号,称

6、为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称 为接收窗口。 发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的序号代表了那些已经被发送, 但是还没有被确认的帧,或者是那些可以被发送的帧。接受方为其窗口内的每一个序号保 留了一个缓冲区。与每个缓冲区相关联的还有一位,用来指明该缓冲区是满的还是空的。若从滑动窗口的观点来统一看待 1 比特滑动窗口、后退 n 及选择重传三种协议,它们的差别仅在于各自窗口尺寸的大小不同而已。1 比特滑动窗口协议:发送窗口 =1,接收窗口 =1;后退 N 协议:发送窗口 >1,接收

7、窗口 =1;选择重传协议:发送窗口>1, 接收窗口 >1。2.2 1bit 滑动窗口协议当发送窗口和接收窗口的大小固定为1 时,滑动窗口协议退化为停等协议( stop and wait )。该协议规定发送方每发送一帧后就要停下来,等待接收方已正确接收的确 认( acknowledgement )返回后才能继续发送下一帧。由于接收方需要判断接收到的帧 是新发的帧还是重新发送的帧,因此发送方要为每一个帧加一个序号。由于停等协议规 定只有一帧完全发送成功后才能发送新的帧,因而只用一比特来编号就够了。其发送方 和接收方运行的流程图如图所示。2.3后退N协议由于停等协议要为每一个帧进行确认后

8、才继续发送下一帧,大大降低了信道利用率,因此又提出了后退n协议。后退 n协议中,发送方在发完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发 来的应答帧,也可以继续发送。且发送方在每发送完一个数据帧时都要设置超时定时 器。只要在所设置的超时时间内仍收到确认帧,就要重发相应的数据帧。如:当发送 方发送了 N个帧后,若发现该N帧的前一个帧在计时器超时后仍未返回其确认信息,则该帧被判为出错或丢失,此时发送方就不得不重新发送出错帧及其后的N帧。从这里不难看出,后退n协议一方面因连续发送数据帧而提高了效率,但另一方面,在重传时又必须把原来已正确传送过的数据帧

9、进行重传(仅因这些数据帧之前有 一个数据帧出了错),这种做法又使传送效率降低。由此可见,若传输信道的传输质 量很差因而误码率较大时,连续测协议不一定优于停止等待协议。此协议中的发送窗 口的大小为 k,接收窗口仍是1。2.4选择重传协议在后退n协议中,接收方若发现错误帧就不再接收后续的帧,即使是正确到达的帧,这显然是一种浪费。另一种效率更高的策略是当接收方发现某帧出错后,其后继续送来的正确的帧虽然不能立即递交给接收方的高层,但接收方仍可收下来,存放在一个缓冲 区中,同时要求发送方重新传送出错的那一帧。一旦收到重新传来的帧后,就可以原已 存于缓冲区中的其余帧一并按正确的顺序递交高层。这种方法称为选

10、择重发(SELECTICEREPEAT),其工作过程如图所示。显然,选择重发减少了浪费,但要求接收方有足够大 的缓冲区空间。2.5流量控制TCP的特点之一是提供体积可变的滑动窗口机制,支持端到端的流量控制。TCP的窗口以字节为单位进行调整,以适应接收方的处理能力。处理过程如下:(1)TCP连接阶段,双方协商窗口尺寸,同时接收方预留数据缓存区;(2 )发送方根据协商的结果,发送符合窗口尺寸的数据字节流,并等待对方的确认;(3)发送方根据确认信息,改变窗口的尺寸,增加或者减少发送未得到确认的字节 流中的字节数。调整过程包括:如果出现发送拥塞,发送窗口缩小为原来的一半,同 时将超时重传的时间间隔扩大

11、一倍。(4)滑动窗口机制为端到端设备间的数据传输提供了可靠的流量控制机制。然而, 它只能在源端设备和目的端设备起作用,当网络中间设备(例如路由器等)发生拥塞 时,滑动窗口机制将不起作用。3. 需求分析3.1课程设计题目:滑动窗口协议仿真3.2 开发环境:Visual C+ 6.03.3运行环境:Windows操作系统3.4课程设计任务及要求:(1)程序按照滑动窗口协议实现端对端的数据传送。包括协议的各种策略,如包丢失、停 等应答、超时等都应有所仿真实现。(2) 显示数据传送过程中的各项具体数据。双方帧的个数变化,帧序号,发送和接受速度,暂停或重传提示等。3.5界面要求:此次课程设计要求的所有功

12、能应可视,我们组主要是用VC+编写的,运行在 DOS环境下,观察发送方(sender)发送数据包到接收方(receive )时。界面应显示出双方帧个数 的变化,帧序号,发送和接受速度,暂停或重传提示等, 界面中必须动态显示数据帧的发送和接受情况,包括在相应的窗口详细显示相应的ACK和其他收发数据帧后发出的消息,以表明模拟协议的正确运作过程。在各种情况下,接受方和发送方窗口应实时显示帧的发送和接 受情况,包括序号,时间戳,内容等。以及窗口的填充和清空情况。3.6网络接口要求:接收数据的端口初始应为监两台机器或是一台机器中两个独立的线程模拟发送方与接受方, 听状态。发送方向接受方发起连接,成功后开

13、始发送数据。4. 概要设计4.1 结构体定义如下:typedef enum data = 1,ack,nak,tout frame kind; / 帧类型typedef struct frame_headframe_kind kind; /帧类型unsigned int seq; /序列号unsigned int ack; /确认号unsigned char dataMAX_LENGTH; / 数据 Head;typedef struct frameframe_head head; /帧头unsigned int size; /数据的大小 Frame;typedef struct framen

14、ode / 队列节点类型 frame head_data;struct framenode *next; Framenode;typedef structFramenode *front; /队头指针Framenode *rear; /队尾指针 LinkQueue;4.2 发送方的主要函数实现:函数名: void InitLine(LinkQueue *q);功 能:初始化队列。函数名: void GetFrameFromHost(LinkQueue *q);功 能:从主机取数据帧,由于实验需要,假设主机有足够多的数据帧要发送。void DeLine(LinkQueue *q);功 能:数据帧

15、发送完毕(收到确认帧)后,删除发送的数据帧(队头)。函数名: int QueueEmpty(LinkQueue *q);功 能:判断队列是否为空。函数名: frame QueueFront(LinkQueue *q);功 能:取队头,首帧是准备好待发送的帧。函数名: int QueueLen(LinkQueue *q);功 能:计算队列长度。函数名: DWORD WINAPI ReceiveFun(LPVOID pArg);功 能:发送线程调用的函数, pArg 参数存接收帧指针。函数名: void main();功 能:发送方主函数, 首先和接收方(本机 "127.0.0.1&qu

16、ot; )建立 socket 连接并初始化发送 队列。然后重复下面的步骤:(1)从主机取数据帧;(2) 发送数据帧,含超时重发(接收方未收到或未收到接收方ack)和错误重发(收到接 收方 nak);(3) 设置超时计时器,这里是5 秒;( 4)等待确认,调用 CreateThread() 函数创建一个线程,超时则调用 TerminateThread() 函数结束线程并再次发送数据帧。收到数据帧则做后续处理;( 5)收到否认帧 nak 则再次发送数据帧,收到确认帧 ack 则发送下一个数据帧;(6)如果发送的测试时间达到20秒,则提示是否继续测试,按 q'或 Q退出测试。4.3 接收方的

17、主要函数实现:函数名: void InitLine(LinkQueue *q);功 能:初始化队列。函数名: void GetFrameFromHost(LinkQueue *q);功 能:准备好接收帧的缓冲池,首帧是待接收的帧,尾帧是已经接收的待提交主机的帧。 由于实验需要,假设数据帧送往主机是足够快的。int DeLine(LinkQueue *q, frame *pf, unsigned int curw)功 能:将帧数据保存供提交主机, curw 是打开的待接收数据的窗口。函数名: int QueueEmpty(LinkQueue *q);功 能:判断队列是否为空。函数名: int Q

18、ueueLen(LinkQueue *q);功 能:计算队列长度。函数名: void main();功 能:接收方主函数,首先和发送方建立 socket 连接并初始化初始化接收窗口。然后重 复下面的步骤:( 1)等待,接收数据帧;(2) 校验数据帧,假定产生随机结果,20%的概率校验错误或发送方发送数据帧超时;(3) 校验错误时,丢弃数据帧,并发送否认帧nak;(4) 如果出现接收超时(假定未收到发送方发送的数据帧),则不给发送发任何回应;并ack。(5) 如果校验正确,首先判断是否是上一帧的重发。是上一帧的重发,则丢弃数据帧, 发送确认帧 ack ;是新的数据帧,则保存数据帧到当前接收窗口,

19、并发送确认帧(6) 送数据帧至主机。5. 源代码5.1 发送方的主要代码:void InitLine(LinkQueue *q)q->front = q->rear = NULL;int QueueEmpty(LinkQueue *q)return q->front = NULL && q->rear = NULL;frame QueueFront(LinkQueue *q)if (QueueEmpty(q)printf(" 队列为空! n");Sleep(SLEEPMS);exit(0);return q->front->

20、;head_data;int QueueLen(LinkQueue *q)if (QueueEmpty(q)return 0;int num = 0;Framenode *p = q->front;while(p != NULL)num+;p = p->next;return num;void GetFrameFromHost(LinkQueue *q)if(QueueLen(q) >= MAXPOOL)printf("data %d 已准备好 n", q->front->head_data.head.seq);return;Framenode

21、 *p=(Framenode *)malloc(sizeof(Framenode);memset(p->head_data.head.data, 0, MAX_LENGTH); srand(unsigned)time(NULL);p->head_data.size = rand() % MAX_LENGTH; / 帧大小随机生成memset(p->head_data.head.data, '1', p->head_data.size);p->head_data.head.ack = -1;p->head_data.head.kind = da

22、ta;p->head_data.head.seq = 0;p->next =NULL;if(QueueEmpty(q)q->front = q->rear=p; /首帧是待发送的帧elsep->head_data.head.seq = (q->rear->head_data.head.seq + 1)%MAXPOOL; q->rear->next =p;q->rear =p;printf(" 从主机得到: data %d ,放入缓存 n", p->head_data.head.seq);GetFrameFro

23、mHost(q); /由于实验需要,假设主机有足够多的数据帧要发送void DeLine(LinkQueue *q)Framenode *p = NULL;if(QueueEmpty(q)printf(" 队列为空! n");elsep = q->front;q->front = p->next;if (q->rear = p) q->rear = NULL;printf(" 发送 data %d, %d 成功!从缓存中删除 n", p->head_data.head.seq, p->head_data.size

24、);free(p);p = NULL;void main()printf(" 建立连接 . n");Begin:WORD wVersionRequested;WSADATA wsaData; / 初始化 socket 库wVersionRequested=MAKEWORD(1,1); / 两个 byte 型合并成一个 WOR型int err=WSAStartup(wVersionRequested,&wsaData);if(err!=0)Sleep(SLEEPMS);return;if ( LOBYTE( wsaData.wVersion ) != 1 | HIBY

25、TE( wsaData.wVersion ) != 1 )WSACleanup(); /中止 Windows Sockets 服务 WSAStartup() 成对使用Sleep(SLEEPMS);return;socketClient = socket(AF_INET,SOCK_STREAM,0);/ 监听的套接字SOCKADDR_IN clientadd;clientadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");clientadd.sin_family = AF_INET;clientadd.sin_port = ht

26、ons(7001);/设置连接端的 IP 、端口连接if(SOCKET_ERROR= connect(socketClient,(SOCKADDR*)&clientadd,sizeof(SOCKADDR) ) /WSACleanup();Sleep(SLEEPMS);goto Begin;char getDataRECEIVE_MAX_LENGTH;memset(getData, 0, RECEIVE_MAX_LENGTH); / 清零if(recv(socketClient,getData,RECEIVE_MAX_LENGTH,0) = SOCKET_ERROR) / printf(

27、" 接受连接提示信息出错! n");elseprintf("%sn",getData);char sendDataSEND_MAX_LENGTH;memset(sendData, 0, SEND_MAX_LENGTH);strcpy(sendData, " 你好接收方,我是发送方! ");if( SOCKET_ERROR = send(socketClient,sendData,strlen(sendData)+1,0) ) / printf(" 发送连接提示信息出错! n");WSACleanup();close

28、socket(socketClient);Sleep(SLEEPMS);return;接受发送printf(" 按任意键继续! n");while (!kbhit() ; / 等待开始Sleep(SLEEPMS);printf("1bit 滑动窗口协议:发送方,发送窗口 =1n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetsend; /dataframe packetreceive; / ack,nakunsigned long tick = GetTickCount();int ret =

29、0;HANDLE hThread;while(1)GetFrameFromHost(&QueueQ); / 从主机取数据帧memset(&packetsend, 0, sizeof(packetsend);Sleep(SLEEPMS);printf("n");packetsend = QueueFront(&QueueQ); / 取数据帧ret = send(socketClient, (char *)&packetsend, sizeof(packetsend), 0);/送 dataif(ret = SOCKET_ERROR)printf

30、(" 发送数据出错! n");continue;printf(" 发送数据帧: data %d, %dn", packetsend.head.seq, packetsend.size); const unsigned long timeOut = 5 * 1000; /设置超时计时器 5 秒超时memset(&packetreceive, 0, sizeof(packetreceive);Sleep(SLEEPMS);printf("n");InitializeCriticalSection(&gCS); / 初始化临

31、界区hThread=CreateThread(NULL, 0, ReceiveFun, (LPVOID)&packetreceive, 0, NULL);int r = WaitForMultipleObjects(1, &hThread, TRUE, timeOut);DeleteCriticalSection(&gCS); / 与 InitializeCriticalSection(&gCS); 成对使用if(ret = SOCKET_ERROR | ret = SOCKET_DISCONN)printf(" 接受出错! Press any key

32、 to continuen");while (!kbhit() ;continue;if(r = WSA_WAIT_TIMEOUT) / 判断超时TerminateThread(hThread, 0); /终止线程printf(" 超时重传: data %d, %dn", packetsend.head.seq,packetsend.size);else if(packetsend.head.seq = packetreceive.head.ack)srand(unsigned)time(NULL);switch(rand() % 5) / 假定产生随机结果, 2

33、0%的概率超时case 0:printf("接 收 方 发 送 回 复 超 时 (ack丢失模拟):%dn",packetsend.head.seq);printf("超时重传:data%d,%dn",packetsend.head.seq,packetsend.size);break;default:if(packetreceive.head.kind = ack)printf(" 接受 ack 帧: ack %dn", packetreceive.head.ack); DeLine(&QueueQ);else if(pac

34、ketreceive.head.kind = nak)printf(" 接受 nak 帧: nak %dn", packetsend.head.seq);break;else printf(" 帧序号出错: %dn", packetreceive.head.ack); if(GetTickCount() - tick > 20 * TIMEOUT) /设置时间 20 秒printf(" 持续时间 20s. 按 q 退出,其他键继续 n");int kbc = getch();if(kbc = 'q' | kbc

35、= 'Q')break;printf(" 按任意键退出! n");while (!kbhit() ;Sleep(SLEEPMS);printf(" 谢谢使用! n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);DWORD WINAPI ReceiveFun(LPVOID pArg)EnterCriticalSection(&gCS);/ 进入 critical section frame *packetreceive = (frame *)pArg;ret = re

36、cv(socketClient, (char *)packetreceive, sizeof(*packetreceive), 0);LeaveCriticalSection(&gCS); / 线程用毕,离开 critical section return ret;5.2 接收方的主要代码:void InitLine(LinkQueue *q)q->front = q->rear = NULL;int QueueEmpty(LinkQueue *q)return q->front = NULL && q->rear = NULL;frame Qu

37、eueFront(LinkQueue *q)if (QueueEmpty(q)printf(" 队列为空! n");Sleep(SLEEPMS);exit(0);return q->front->head_data;int QueueLen(LinkQueue *q)if (QueueEmpty(q)return 0;int num = 0;Framenode *p = q->front;while(p != NULL)num+;p = p->next;return num;int GetFrameFromHost(LinkQueue *q)if(Q

38、ueueLen(q) >= MAXPOOL)printf(" 准备接受: data %d n", q->front->head_data.head.seq);return q->front->head_data.head.seq;Framenode *p=(Framenode *)malloc(sizeof(Framenode);memset(p->head_data.head.data, 0, MAX_LENGTH);p->head_data.head.ack = -1;p->head_data.head.kind = ac

39、k;p->head_data.head.seq = 0;p->next =NULL;if(QueueEmpty(q)q->front = q->rear=p;elsep->head_data.head.seq = (q->rear->head_data.head.seq + 1)%MAXPOOL; q->rear->next =p;q->rear = p;return GetFrameFromHost(q);int DeLine(LinkQueue *q, frame *pf, unsigned int curw) /假设数据帧送往主

40、机是足够快的Framenode *p = NULL;if(curw = q->front->head_data.head.seq)p = q->front;elsep = q->rear;if(p->head_data.head.ack != -1) / 假定数据已经提交主机printf(" 向 主 机 交 付 data %d, %d 成 功 ! n", p->head_data.head.ack, p->head_data.size);memset(p->head_data.head.data, 0, MAX_LENGTH)

41、; memcpy(p->head_data.head.data, pf->head.data, pf->size);p->head_data.size = pf->size;p->head_data.head.ack = pf->head.seq; / 保存发送帧序号return p->head_data.head.seq;frame QueueAnswer(LinkQueue *q, unsigned int curw)if(curw = q->front->head_data.head.seq)return q->front

42、->head_data;elsereturn q->rear->head_data;void main()Begin:WORD wVersionRequested;WSADATA wsaData; / 初始化 socket 库wVersionRequested = MAKEWORD( 1, 1 ); /两个 byte 型合并成一个 WOR型int err = WSAStartup(wVersionRequested, &wsaData );/使用 sockets 之前要调用一次if ( err != 0 )Sleep(SLEEPMS);return;if ( LOBY

43、TE( wsaData.wVersion ) != 1 | HIBYTE( wsaData.wVersion ) != 1 )WSACleanup();/ 中止 Windows Sockets 服务 WSAStartup() 成对使用 Sleep(SLEEPMS);return;SOCKET socksrv = socket(AF_INET,SOCK_STREAM,0);/ 监听的套接字 SOCKADDR_IN socketadd;socketadd.sin_addr.S_un.S_addr = htonl(INADDR_ANY); / 监听连接 socketadd.sin_family =

44、AF_INET;socketadd.sin_port = htons(7001); /设置端口if( SOCKET_ERROR = bind(socksrv,(SOCKADDR*)&socketadd,sizeof(SOCKADDR) ) printf(" 绑定出错! n");WSACleanup();Sleep(SLEEPMS);return;if( SOCKET_ERROR = listen(socksrv,5) )printf(" 监听出错! ");WSACleanup();Sleep(SLEEPMS);return;SOCKADDR_IN

45、 sockclient;int len = sizeof(SOCKADDR);建立连接的套节SOCKET sockconn = accept(socksrv,(SOCKADDR*)&sockclient,&len);/ 字if(INVALID_SOCKET = sockconn )printf(" 建立连接出错! n");WSACleanup( );Sleep(SLEEPMS);return;char sendDataSEND_MAX_LENGTH;memset(sendData, 0, SEND_MAX_LENGTH);sprintf(sendData,&

46、quot;%s"," 你好发送方,我是接受方! ");if( SOCKET_ERROR = send(sockconn,sendData,strlen(sendData)+1,0) )printf(" 发送连接提示信息出错! n");WSACleanup( );closesocket(sockconn);Sleep(SLEEPMS);return;char getDataRECEIVE_MAX_LENGTH;memset(getData, 0, RECEIVE_MAX_LENGTH);recv(sockconn,getData,RECEIVE_

47、MAX_LENGTH,0);printf("%sn",getData);printf("1bit 滑动窗口协议:接收方,接收窗口 =1n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetreceive; /dataframe packetsend; / ack,nakint curw = GetFrameFromHost(&QueueQ);/初始化接收窗口int ret = 0;while(1)memset(&packetreceive, 0, sizeof(packetrecei

48、ve);Sleep(SLEEPMS);printf("n");ret = recv(sockconn,(char *)&packetreceive, sizeof(packetreceive), 0);if(ret = SOCKET_ERROR | ret = SOCKET_DISCONN)if(ret = SOCKET_ERROR)printf(" 连接出错!自动连接! n");continue;elsen");printf(" 连接已断开,按 q 退出,其他键等待新的连接 int kbc = getch();if(kbc

49、= 'q' | kbc = 'Q')break;elseWSACleanup();closesocket(sockconn);Sleep(SLEEPMS);goto Begin;srand(unsigned)time(NULL);switch(rand() % 5) / 假定产生随机结果, 20%的概率校验错误或接收发送方超时case 0:printf(" 接受数据帧: data %d, %d ,校验错误,丢弃 ( 数据帧出错模拟 )n", packetreceive.head.seq, packetreceive.size);memset(

50、&packetsend, 0, sizeof(packetsend);memcpy(&packetsend, &packetreceive, sizeof(packetreceive);packetsend.head.ack = packetreceive.head.seq;packetsend.head.seq = curw;packetsend.head.kind = nak;printf(" 发送否认帧: nak %dn", packetreceive.head.seq);break;case 1:packetsend.head.kind =

51、tout;printf(" 发 送 方 发 送 数 据 超 时 ( 数 据 帧 丢 失 模 拟 ) : %dn", packetreceive.head.seq);break;default:printf(" 接受数据帧: data %d, %d ,校验正确 n", packetreceive.head.seq, packetreceive.size);if(packetreceive.head.seq = (QueueAnswer(&QueueQ, curw).head.ack)printf(" 上 一 帧 的 重 发 , 丢 弃 ,

52、 直 接 发 送 确 认 帧 : ack %dn", packetreceive.head.seq);elseprintf(”新的数据帧:data %d, %d放入缓存n".packetreceive.head.seq,packetreceive.size);curw = DeLine(&QueueQ, &packetreceive, curw); /将新帧保存待送往主memset(&packetsend, 0, sizeof(packetsend);packetsend = QueueAnswer(&QueueQ, curw); /待发送的确认帧printf(" 发送确认帧: ack %dn", packetreceive.head.seq);packetsend.head.kind = ack;break;if(packetsend.head.kind = tout) continue; /发

温馨提示

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

评论

0/150

提交评论