当前位置:文档之家› 停止等待协议的实现

停止等待协议的实现

福建农林大学计算机与信息学院课程设计报告课程名称:计算机网络课程设计题目:停止等待协议的实现姓名:系:计算机专业:计算机科学与技术年级:学号:指导教师:职称:2011 年6 月10 日福建农林大学计算机与信息学院课程设计报告结果评定目录1、课程设计的目的和任务 (4)2、课程设计的要求 (4)3、课程设计的分析与设计 (4)设计任务分析 (4)设计方案论证 (5)详细设计 (5)3、系统实施 (7)4、总结与体会 (9)5、参考文献 (9)附录:源代码 (10)停止等待协议的实现1、课程设计的目的和任务《计算机网络》课程讲述计算机网络的原理,尤其是TCP/IP协议栈的原理和应用,是一门理论性、应用性、实践性都比较强的课程。

而此次的课程设计是在学习完《计算机网络》课程后进行的一次全面的综合能力的检验。

计算机网络的课程设计是从原理和实践的角度,在计算机上编程模拟实现计算机网络的基本协议。

通过本次课程设计,使我们对计算机网络的原理能有更加深刻的认识和理解,同时进一步锻炼自己的动手能力。

在这次课程设计中,我设计的的是通过编译语言,编程模拟实现数据链路层协议中的停止等协议。

2、课程设计的要求通过双方的收发数据而达到相互通信的目的。

3、课程设计的分析与设计设计任务分析停止等待协议是数据链路层的几个协议中最简单的协议,是具有最简单流量控制的数据链路层协议,是数据链路层各种协议的基础。

此课程设计是基于winsock 编程,是在VC++的MFC界面下和控制台下实现的。

它采用客户机/服务器(C/S)模型,即发送数据的一端为客户端,接收数据的一端为服务器端。

停止等待协议就是通过双方的收发数据而达到相互通信的目的。

本课程设计通过编程模拟实现停止等待协议,随机的发送数据,通过服务器的的接受结果和客户端的接受结果显示理解停止等待协议的原理,掌握其应用。

设计方案论证当收方收到一个正确的数据帧后,便会向发方发送一个确认帧ACK,表示发送的数据正确接收。

当发方收到确认帧后才能发送一个新的数据帧,这样就实现了接收方对发送方的流量控制。

由于通信线路质量各方面的影响,数据帧从发送方到接收方传输的过程中可能会出现差错。

为了保证数据的正确性和完整性,接收方在收到数据后,会用一定的方法对接收到的数据进行差错检验,所以接收方很容易检测出收到的数据帧是否出现差错。

当接收方发现收到的数据出现差错时,就会向发送方发送一个否认帧NAK,表示对方发送的数据错误。

发送方会根据接收方发来的信息做出相应的操作。

采用这样的有效的检错机制,数据链路层可以对上面的网络层提供了可靠的传输的服务。

详细设计停止等待协议的算法如下:为了对停止等待算法有一个完整而准确的理解,下面给出此协议的算法。

具有最简单流量控制的数据链路层协议假定1:链路是理想的传输信道,所传送的任何数据既不会出差错也不会丢失。

假定2:不管发方以多快的速率发送数据,收方总是来得及收下,并及时上交主机。

这个假定就相当于认为:接收端向主机交付数据的速率永远不会低于发送端发送数据的速率。

现在去掉上述的第二个假定。

但是,仍然保留第一个假定,即主机 A 向主机B 传输数据的信道仍然是无差错的理想信道。

然而现在不能保证接收端向主机交付数据的速率永远不低于发送端发送数据的速率。

由收方控制发方的数据流,乃是计算机网络中流量控制的一个基本方法。

简单解释:收方每接受到发方一帧后,回复确认帧,让发方继续发送下一帧,并且收方将数据帧交给上层软件识别,出现错误就将帧丢掉.在接收结点:(1) 等待。

(2) 若收到由发送结点发过来的数据帧,则将其放入数据链路层的接收缓存。

(3) 将接收缓存中的数据帧上交主机。

(4) 向发送结点发一信息,表示数据帧已经上交给主机。

(5) 转到(1)在发送结点:(1) 从主机取一个数据帧。

(2) 将数据帧送到数据链路层的发送缓存。

(3) 将发送缓存中的数据帧发送出去。

(4) 等待。

(5) 若收到由接收结点发过来的信息(此信息的格式与内容可由双方事先商定好),则从主机取一个新的数据帧,然后转到(2)。

因此,在设计编程模拟实现停止等待协议时,因具体考虑有关帧的一些知识。

帧的结构:帧的类型帧的序号帧的确认号数据信息(可变)校验位帧的结构帧的类型(frame_kind)分为数据帧(data_frame),确认帧(ack_frame)和否认帧(nak_frame)三种。

发送方向接收方发送数据,是以帧为单位的,就称为数据帧。

它的数据信息是可变的,但最佳的帧长为1500个字节。

接收方接收数据后,会对收到的数据帧进行差错校验,当数据正确时,就会向发送方发送一个确认帧,以表示发送方发送的数据正确接收了,反之,就会向发送方发送一个否认帧,并把这个出错的数据帧丢弃。

帧的序号(seq):由于采用的是单工通信,帧的结构中用的控制域也很少,这个域会随着帧类型的不同而不同:对数据帧来说:序号(seq)表示的是发送端发送的帧的序号。

对确认帧来说:序号(seq)表示的是接收方希望接收到的帧的序号,它表示seq 以前的各帧都已经正确接收,希望收到序号为seq的帧。

对否认帧来说:序号(seq)也是表示接收方希望收到的数据帧的序号,表示接收方已经收到序号为seq的帧,但是这个帧出现错误,希望发送方重新发送该数据帧。

停止等待协议采用的是单工通信,接收端向发送端发送的确认帧和否认帧中没有数据信息,它们的数据域为空。

由于是单工通信,发送方只发送数据,所以发送方帧的“帧的确认号”中并没有包含任何的确认信息。

3、系统实施此次课程设计通过C++编程基本上模拟实现了数据链路层中的停止等待协议,但是程序中存在一定的不足,没有能够完全的体现停止等待协议的的工作原理。

在此课程设计中,数据的发送是随机生成的。

运行结果截图如下所示:服务器端的运行截图:客户端的运行截图:结果如下所示:客户端:服务器端:4、总结与体会经过这几天的课程设计,通过查阅相关的资料和以前的学习以及和同学之间的交流最终能够较成功的实现该课程设计。

停止等待协议是数据链路层的一个重要协议,也是计算机网络中的一个重要协议。

在进行课程设计时我遇到了不少的困难,通过同学的帮助和查阅相关的资料,最终解决了问题,模拟实现了停止等待协议。

在设计过程中,刚开始时,没有能够实现客户端和服务器的连接,最终导致客户端发送数据的失败,从而导致服务器端的接收失败。

经过查阅相关的资料,找到了错误的所在,并实现了停止等待协议的功能。

此外,此次课程设计中的一个难点就是客户端发送数据采用的是随机函数rand()产生随机发送的数据。

5、参考文献谢希仁《计算机网络》电子工业出版社附录:源代码发送端:()#include <>#include <>#include <>#pragma comment(lib,"")#define SERVER_PORT 7300 //侦听端口客户端向服务器传送的结构:struct BAG{ char packet;};void main(int argc, char *argv[]){WORD wVersionRequested;WSADATA wsaData;int ret,i,ra,data=0;SOCKET sClient,sListen;struct sockaddr_in saServer;//地址信息struct BAG bag;char *ptr = (char *)&bag;BOOL fSuccess = TRUE;WinSock初始化:wVersionRequested = MAKEWORD(2, 2);//希望使用的WinSock DLL的版本ret = WSAStartup( wVersionRequested, &wsaData );if (ret != 0){printf("WSAStartup() failed!\n");return;}确认WinSock DLL支持版本:if (LOBYTE != 2 || HIBYTE( ) != 2 ){WSACleanup();printf("Invalid Winsock version!\n");return;}创建socket,使用TCP协议:sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(sClient == INVALID_SOCKET){WSACleanup();printf("socket() failed!\n");return;}构建服务器地址信息:= AF_INET;//地址家族= htons(SERVER_PORT);//转化为网络字节序连接服务器:ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer)); if (ret == SOCKET_ERROR){printf("connect() successed!\n");closesocket(sClient);//关闭套接字WSACleanup();return;}按照预定协议,客户端将发送一个数字:for(i=97;i<=104;i++){ra = rand()%11;if(ra%5 == 1) data+=i;else data=i;=data;ret = send(sClient, (char *)&bag, sizeof(bag), 0);ret = recv(sListen, ptr, sizeof(bag), 0);if!=i){i--;printf("send()successed!\n");continue;}else if==i)printf("packet %d has been sent!\n",i+1);}closesocket(sClient); WSACleanup();}接受端():#include <>#include <>#include <>#include <>#pragma comment(lib,"")#define SERVER_PORT 7300 //侦听端口客户端向服务器传送的结构:struct BAG{ char packet;};void main(){WORD wVersionRequested;WSADATA wsaData;int ret,nLeft,length;SOCKET sListen, sServer; //侦听套接字,连接套接字struct sockaddr_in saServer, saClient;//地址信息struct BAG bag;char *ptr,*pp;WinSock初始化:wVersionRequested = MAKEWORD(2, 2);//希望使用的WinSock DLL的版本ret = WSAStartup(wVersionRequested, &wsaData);if (ret != 0){printf("WSAStartup() failed!\n");return;}确认WinSock DLL支持版本:if (LOBYTE != 2 || HIBYTE( ) != 2 ){WSACleanup();printf("Invalid Winsock version!\n");return;}创建Socket,使用TCP协议:sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(sListen == INVALID_SOCKET){WSACleanup();printf("socket() failed!\n");return;}构建本地地址信息:= AF_INET;//地址家族= htons(SERVER_PORT);//转化为网络字节序= htonl(INADDR_ANY);//使用INADDR_ANY指示任意地址绑定:ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer)); if (ret == SOCKET_ERROR){printf("bind() failed! code:%d\n", WSAGetLastError());closesocket(sListen);//关闭套接字WSACleanup();return;}侦听连接请求:ret = listen(sListen, 5);if (ret == SOCKET_ERROR){printf("listen() failed! code:%d\n", WSAGetLastError());closesocket(sListen);//关闭套接字WSACleanup();return;}printf("Waiting for client connecting!\n");printf("tips : Ctrl+c to quit!\n");阻塞等待接受客户端连接:length = sizeof(saClient);sServer = accept(sListen, (struct sockaddr *)&saClient, &length); if(sServer == INVALID_SOCKET){ printf("accept() failed! code:%d\n", WSAGetLastError());closesocket(sListen);//关闭套接字WSACleanup();return;}printf("Accepted client: %s:%d\n",inet_ntoa, ntohs);按照预定协议,客户端将发来一个信息:nLeft = sizeof(bag);ptr = (char *)&bag;for(int i=97;i<=104;i++){接收数据:pp=ptr;ret = recv(sServer, ptr, nLeft, 0);if(ret == SOCKET_ERROR){ printf("recv() failed!\n");break;}else if!=i){printf("wrong packet!\n");i--;ret = send(sServer, pp, nLeft, 0);continue;}else if==i){printf("recv() %c successd!\n",i);ret = send(sServer, ptr, nLeft, 0);}客户端已经关闭连接:if(ret == 0){printf("client has closed the connection!\n");break;}}closesocket(sListen);//关闭套接字closesocket(sServer);WSACleanup();。

相关主题