停止等待协议实验报告(共16页).docx

上传人:飞****2 文档编号:14238801 上传时间:2022-05-03 格式:DOCX 页数:16 大小:340.65KB
返回 下载 相关 举报
停止等待协议实验报告(共16页).docx_第1页
第1页 / 共16页
停止等待协议实验报告(共16页).docx_第2页
第2页 / 共16页
点击查看更多>>
资源描述

《停止等待协议实验报告(共16页).docx》由会员分享,可在线阅读,更多相关《停止等待协议实验报告(共16页).docx(16页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、精选优质文档-倾情为你奉上实验 停止等待协议分析与协议模拟实现一、 实验目的和任务1.掌握停止等待协议的原理及分析过程包括使用状态转移图进行协议的分析。2.在计算机上编程模拟停止等待协议的工作过程并实现文件的端到端传输。3.能够在文件的传输过程中表现出协议运行所遇到的各种状况,如丢包,差错控制等二、 分析与设计1.设计任务分析:停止等待协议是数据链路层的几个协议中最简单的协议,是具有最简单流量控制的数据链路层协议,是数据链路层各种协议的基础。实验是基于winsock编程,是visual C+6.0 win32控制台运用程序实现的。它采用客户机/服务器(C/S)模型,即发送数据的一端为客户端,接

2、收数据的一端为服务器端。停止等待协议就是通过双方的收发数据而达到相互通信的目的。本实验通过编程模拟实现停止等待协议,随机的发送文件,通过服务器的的接受结果和客户端的接受结果显示理解停止等待协议的原理,掌握其应用。2. 协议分析假定 1: 链路是理想的传输信道,所传送的任何数据既不会出差错也不会丢失。假定 2: 不管发方以多快的速率发送数据,收方总是来得及收下,并及时上交主机。这个假定就相当于认为:接收端向主机交付数据的速率永远不会低于发送端发送数据的速率。 如果存在这样的传输信道,数据链路层协议也是不需要的。信道不会出错,而且接收方缓存的容量为无限大而永远不会溢出;或接收速率与发送速率绝对精确

3、相等。在上述两个假定的情况下,数据链路层当然就不需要任何协议就可以保证数据传输的正确。这就是说,传输数据的信道是不可靠的(即不能保证所传的数据不产生差错),并且还需要对数据的发送端进行流量控制。现在不能保证接收端向主机交付数据的速率永远不低于发送端发送数据的速率。由收方控制发方的数据流收方每接受到发方一帧后,回复确认帧,让发方继续发送下一帧,并且收方将数据帧交给上层软件识别,出现错误就将帧丢掉. 在大多数协议中,流量控制是一组过程,这组过程是用来告诉发送方在等待接收方的应答信号之前最多可以传送多少数据。流量控制有两个要点:(1)数据流不能使接收方过载。任何接收设备都有一个处理输入数据的速率限制

4、,并且存储输入数据的存储器容量也是有限的。接收设备必须在达到这些限制之前通知发送设备并且请求发送设备发送较少的数据帧或是暂停一会儿。在使用输入数据之前,需要对数据进行校验和处理,因此,每个接收设备都有一块存储器,叫做缓冲区,用于存放未来得及处理的数据帧。如果缓冲区将满,接收方也必须能够通知发送方暂停传输,直到接收方又能接收数据。(2)应答。随着数据帧的到来,接收方对他们进行应答,可以每收到一帧给一个应答,也可以一次对若干帧进行应答。如果一个帧到达时已经被破坏,接收方发送一个否定应答帧(NAK)。在数据链路层,差错控制主要指错误检测和重传方法。在一个帧中出现任何一个错误,接收方就返回一个否定应答

5、帧,出错的帧就被发送方重新传送。这个过程被称作自动重复请求(ARQ)。数据被重传的情况有三种:帧破坏、帧丢失和应答帧丢失。流量控制和差错控制是结合在一起实现的,共有两种实现流量控制和差错控制的技术:停止等待协议和滑动窗口协议。可以用多种方法来表示一个有限状态机,对协议进行描述,以下只描述一种。1)混合描述方法比较实用的办法是合并一些状态,即考虑一些次要的细节。例如,甲方的状态 1 和状态 2,状态 3和状态 4 都可以合并,乙的状态 1 和状态 4,状态 2 和状态 3 也可进行合并。这样可以用 3 个字符 XYZ 表示整个系统的状态,其中 X0 或 1,对应于甲方准备发 0 或 1(包括发完

6、后等待 ACK 的状态);Y0 或 1,对应于乙方期望收到 0 或 1;Z0、l、A或,对应于信道上传送的是 0、1、ACK 或出现了差错(包括丢失)。这样,就可得出 图3-24 的有限状态机。在弧线(或直线)旁边注明的数字为状态变迁的标号,其意义也注明在 图3-24 的右方。假设系统一开始处在(000)状态。这表示甲发完 0,乙期望收到 0,而信道上传送的也是 0。在无差错的情况下,系统的状态仅在 4 个状态中循环:(000)(01A)(111)(10A)(000) 。从理论上讲,应当共有 2 2 4 = 16 种不同的状态。去掉没有意义的组合后,还剩下 10 种状态,而导致状态变迁的输人事

7、件共有 9 种( 标号 0 8 )。这种有限状态机可帮助我们检查协议是否正确。例如,检查一下乙方会不会连续将两个 0 号帧送交主机。这相当于检查一下会不会出现这种情况,即在两次出现状态变迁 1 之间不出现状态变迁 3 。仔细检查 图3-24 就可发现这种情况是不会发生的。同样方法也可用来排除连续将两个 1 号帧送交主机的可能。再检查一下会不会发生甲方连续改变状态 2 次( 如从 0 到 1,再回到 0 )而乙方的状态未改变。这种情况相当于出现了未被发现的报文丢失。可以看出,这种情况也是不存在的。协议必须不出现死锁。死锁的出现是因为存在着这样的一种状态子集,其特点是:从这一子集内变迁到子集外是不

8、可能的,而在这一子集内状态的变迁总是局限于子集内的几个状态。可以看出,如图 所示的自动机没有死锁现象。3设计方案论证当收方收到一个正确的数据帧后,便会向发方发送一个确认帧ACK,表示发送的数据正确接收。当发方收到确认帧后才能发送一个新的数据帧,这样就实现了接收方对发送方的流量控制。由于通信线路质量各方面的影响,数据帧从发送方到接收方传输的过程中可能会出现差错。为了保证数据的正确性和完整性,接收方在收到数据后,会用一定的方法对接收到的数据进行差错检验,所以接收方很容易检测出收到的数据帧是否出现差错。当接收方发现收到的数据出现差错时,就会向发送方发送一个否认帧NAK,表示对方发送的数据错误。发送方

9、会根据接收方发来的信息做出相应的操作。采用这样的有效的检错机制,数据链路层可以对上面的网络层提供了可靠的传输的服务。三、 系统运行与验证程序分两部分:客户程序和服务器程序。工作过程是: 服务器首先启动,它创建套接字之后等待客户的连接;客户启动后创建套接字,然后和服务器建立连接;建立连接后,客户写入文件的路径,然后将文件发送到服务器,服务器要求写入保存的文件路径,收到到文件后,将接收到的文件保存到指定路径当中。服务器端运行图: 客户端运行图成功发送文件后的服务器端客户端文件发送失败 客户端的响应客户端向服务器端发送文件请求ENQ,但是没有收到返回帧,客户端显示send file failed,而

10、file send failed表明文件经过规定次数重传后文件还是发送失败。四、 总结与体会1. 分组情况 张润:负责停止等待协议模拟客户端程序的编写、调试。毛凤阳:负责停止等待协议模拟服务端程序的编写、调试。黄晓明:负责查阅相关资料,实验报告的撰写,编写头文件。2. 总结通过本次实验及课上老师讲解,对停止等待协议有了更深刻的了解。并且通过C/S代码的编写运行,形象地看到客户/服务器端的运作方式,对于C/S模型有了很深刻的印象以及进一步理解。通过代码的编写,再一次熟悉Socket编程原理,掌握简单的套接字编程。运行程序成功后,是在同一台电脑上进行C与S端的连接。而且使用的是TCP协议,所以要模

11、拟停止等待协议发送丢包,超时等情况比较困难。仅仅实现了文件发送时等待应答信号超时的情况。编程时遇到许多困难,从一个新手通过查阅相关的资料和以前的学习以及和同学之间的交流进步到逐步了解。在设计过程中,组员之间相互促进,相互交流,共同进步。发送端程序/ sender.cpp : 定义控制台应用程序的入口点。/#include stdafx.h#include #include #include #include ./header/ARQ.h#include ./header/Exception.h/ 服务器端口#define SERVER_PORT 2280/最大重传次数#define MAXRE

12、TRY 8/传送传时时间#define TIMEOUT 3000#pragma comment(lib,ws2_32.lib)/设置link时的lib库,加入ws2_32.lib到工程,此库文件与socket编程有关 /也可以在MFC中通过在project-settings-link中加入 /主要是获得Ws2_32.dll using namespace std;SOCKET PrimaryUDP;/定义一个socket号char ServerIP20;/定义数组保存服务器的IP地址char FilePathMAX_PATH;/定义文件的路径存储数/ 用作奇偶检校的序号bool g_numbe

13、r = false;/返回的控制字符char g_bcc;HANDLE m_hEvent;void InitWinSock() /初始化socketWSADATA wsaData;/The WSADATA structure is used to store Windows Sockets initialization information /returned by a call to the AfxSocketInit global function.if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)/The WSAStartup function

14、 initiates use of Ws2_32.dll by a process. /The MAKEWORD macro creates a WORD value by concatenating the specified values. throw Exception(Windows sockets 2.2 startup unsuccessful);elseprintf(Using %s (Status: %s)n,wsaData.szDescription, wsaData.szSystemStatus);printf(with API versions %d.%d to %d.%

15、dnn,LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion);void mksock(int type) /创建socket号PrimaryUDP = socket(AF_INET, type, 0);/socket()函数创建一个socket号if (PrimaryUDP 0)throw Exception(create socket error);void BindSock() /绑定一个socket号和本地进程(用地址和端口

16、号描述)sockaddr_in sin; /定义一个套接字地址sin.sin_addr.S_un.S_addr = INADDR_ANY;/ 获取本地IP地址sin.sin_family = AF_INET; /协议族TCP/IPsin.sin_port = 0; /系统随机获取端口号if (bind(PrimaryUDP, (struct sockaddr*)&sin, sizeof(sin) 0)/绑定throw Exception(bind error);bool ASendto()sockaddr_in remote;remote.sin_addr.S_un.S_addr = inet

17、_addr(ServerIP);remote.sin_family = AF_INET;remote.sin_port = htons(SERVER_PORT);int fromlen = sizeof(remote);/打开文件FILE * file;if(file = fopen(FilePath, rb) = NULL)/rb说明文件只读并按二进制方式打开coutFilePath open errorendl;return false;coutfile open succeedendl;/ 设置文件指针位置SetFilePointer(file, 0, NULL, FILE_BEGIN)

18、;/使FILE_BEGIN指向文件开头BSC bsc;bsc.header = STX;bsc.tail = ETX;/设置为有信号状态SetEvent(m_hEvent);/分段序号bool number = false;unsigned long dwRead = -1;bool sendComplete = false;while(!sendComplete)/清空数据memset(bsc.data, 0, MAXBSCLENGTH);/把bsc.data前MAXBSCLENGTH字符用代替/当前分块的奇偶序号bsc.number=number;/记录当前的分块序号g_number =

19、bsc.number;if (dwRead =-1)/第一次应发送文件请求消息/发送文件请求bsc.bcc = ENQ;/询问coutENQ;char * filename = FilePath;if (filename = strrchr(FilePath,)=NULL)/在FilePath中寻找字符,返回指向最后一个字符的指针filename = FilePath;/获取文件名else+filename;strcpy(bsc.data,filename);dwRead = 0;elseif(!feof(file)/如果没有检查到file的结束符bsc.bcc = SYN; /同步coutS

20、YN;int i = fread(bsc.data, sizeof(char),MAXBSCLENGTH , file);/把文件读入bsc.data,返回字节数coutread:itsend:sizeof(bsc.data)endl;dwRead+=i;/deRead等于读到的字节数else/发送完毕bsc.bcc = EOT;/结束coutEOT;sendComplete = true;coutsend complete.send size:dwReadendl;fclose(file);/MAXRETRY为最大达重传次数for(int i=0;iMAXRETRY;i+)sendto(Pr

21、imaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,fromlen);ResetEvent(m_hEvent);/设置为无信号状态DWORD reslut = WaitForSingleObject(m_hEvent,TIMEOUT);/等待信号的到来,如果在TIMEOUT时间内信号不到来, /线程不再等待,函数返回,如果想让线程一直等待,需设置该参数为INFINITEif (reslut = WAIT_OBJECT_0)/说明事件是有信号状态返回/收到应答消息,一种是ACK,一种是NAKif (g_bcc = NAK)if (i = M

22、AXRETRY -1)return false;/继续重传continue;else/收到应答消息coutsend succeedendl;break;else if(i = MAXRETRY-1)/没有收到返回帧coutsend file failedendl;return false;/开始发下一段数据number = !number;return true;DWORD WINAPI ARecv(LPVOID lpParam)sockaddr_in remote;int sinlen = sizeof(remote);BSC buffer;int iread = 0;while (true

23、)iread = recvfrom(PrimaryUDP,(char*)&buffer,sizeof(buffer),0,(sockaddr*)&remote,&sinlen);/处理ACK与NAKif (iread = SOCKET_ERROR)continue;/与当前的分块序号进行比较,看是不是当前块的应答if (buffer.number!=g_number)continue;if (buffer.bcc = ACK | buffer.bcc = NAK)/保存返回的控制字符g_bcc = buffer.bcc;SetEvent(m_hEvent);/设置为有信号状态return 0;

24、int _tmain(int argc, _TCHAR* argv) /main函数InitWinSock();mksock(SOCK_DGRAM);BindSock();coutServerIP;coutFilePath;m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);/If the function succeeds, the return value is a handle /to the event object. /创建一个空事件对象,返回一个句柄CreateThread(NULL, 0, ARecv, NULL, 0, NULL);

25、/The CreateThread function creates a thread to execute /within the virtual address space of the calling process. /执行ARecv函数if (!ASendto()coutfile send failedendl;getchar();getchar();getchar();return 0;接收端程序:/ receiver.cpp : 定义控制台应用程序的入口点。#include stdafx.h#include #include #include ./header/ARQ.h#inc

26、lude ./header/Exception.h/ 服务器端口#define SERVER_PORT 2280#pragma comment(lib,ws2_32.lib)/设置link时的lib库using namespace std;SOCKET PrimaryUDP;char FileSavePathMAX_PATH;void InitWinSock()WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)throw Exception(Windows sockets 2.2 startup unsuccessful

27、);elseprintf(Using %s (Status: %s)n,wsaData.szDescription, wsaData.szSystemStatus);printf(with API versions %d.%d to %d.%dnn,LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion);void mksock(int type)PrimaryUDP = socket(AF_INET, type, 0);if (Pr

28、imaryUDP 0)throw Exception(create socket error);void BindSock()sockaddr_in sin;sin.sin_addr.S_un.S_addr = INADDR_ANY;sin.sin_family = AF_INET;sin.sin_port = htons(SERVER_PORT);if (bind(PrimaryUDP, (struct sockaddr*)&sin, sizeof(sin) 0)throw Exception(bind error);DWORD WINAPI ARecv(LPVOID lpParam)FIL

29、E * file = NULL;sockaddr_in remote;int sinlen = sizeof(remote);BSC buffer,bsc;bsc.header = STX;bsc.tail = ETX;memset(bsc.data, 0, MAXBSCLENGTH);int iread = 0;unsigned long dwReceived = 0;bool number = true;/发送方的数据开始发送时的序号设为,为了判断是不是第一次一段数据,所以这里标为while (true)iread = recvfrom(PrimaryUDP,(char*)&buffer,

30、sizeof(buffer),0,(sockaddr*)&remote,&sinlen);if (SOCKET_ERROR = iread | buffer.header != STX | buffer.tail != ETX)/数据错误,发送负应答coutreceived a error dataendl;bsc.bcc = NAK;bsc.number=false;/number这时没有实际的意义sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;if (buffer.number

31、= number)/重复收到数据,发送应答消息coutreceived a repeat dataendl;bsc.bcc = ACK;bsc.number = buffer.number;sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;switch(buffer.bcc)case ENQ:number = !number;/准备接收下一段数据/文件请求coutreceived a file request message,filename:buffer.dataendl;/打开文件

32、if(strcmp(FileSavePath+strlen(FileSavePath)-1),)!=0)strcat(FileSavePath,);strcat(FileSavePath,buffer.data);if(file = fopen(FileSavePath, ab) = NULL)coutfile open failedendl;return -1;break;case SYN:number = !number;/文字发送中int i =0;if(i=fwrite(buffer.data, sizeof(char), sizeof(buffer.data), file) = 0)

33、cout write failed endl;return -1;dwReceived += i;coutwrite:itreceived:sizeof(buffer.data)endl;break;case EOT:number = !number;/文件发送完毕coutfile received completely,save path:FileSavePath,received size:dwReceivedendl;fclose(file);break;default:/数据错误,发送负应答bsc.bcc = NAK;bsc.number=false;sendto(PrimaryUDP

34、,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);continue;break;/发送应答消息bsc.bcc = ACK;bsc.number = buffer.number;sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);return 0;int _tmain(int argc, _TCHAR* argv)InitWinSock();mksock(SOCK_DGRAM);BindSock();CreateThread(NULL, 0, ARecv, NULL, 0, NULL);coutFileSavePath;coutreceiver start succeedendl;getchar();getchar();return 0;专心-专注-专业

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com