停止等待协议 实验指导.docx

上传人:b****5 文档编号:5758970 上传时间:2023-01-01 格式:DOCX 页数:9 大小:22.82KB
下载 相关 举报
停止等待协议 实验指导.docx_第1页
第1页 / 共9页
停止等待协议 实验指导.docx_第2页
第2页 / 共9页
停止等待协议 实验指导.docx_第3页
第3页 / 共9页
停止等待协议 实验指导.docx_第4页
第4页 / 共9页
停止等待协议 实验指导.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

停止等待协议 实验指导.docx

《停止等待协议 实验指导.docx》由会员分享,可在线阅读,更多相关《停止等待协议 实验指导.docx(9页珍藏版)》请在冰豆网上搜索。

停止等待协议 实验指导.docx

停止等待协议实验指导

停止等待协议

1.实验目的1

2.协议介绍1

2.1 停止等待协议的简单介绍(STOP AND WAIT):

1

2.2 帧的结构:

1

2.3 停等协议中相关事件的介绍2

3.实验内容和步骤3

3.1步骤:

3

3.2基本内容:

4

3.3扩展内容:

4

4.实验要求4

5.程序说明5

5.1主要的数据结构介绍:

5

5.2 主要函数介绍:

6

5.3 重点和难点介绍:

7

6.参考资料9

 

1.实验目的

了解winsock编程的基本流程

掌握停止等待协议的基本原理

理解数据链路层的主要功能(数据出错控制,数据重复控制,数据丢失控制等等)

分析简单的协议数据单元

掌握停止等待协议的运行机制

了解停止等待协议的定量分析

2.协议介绍

2.1 停止等待协议的简单介绍(stop and wait):

 

停止等待协议是数据链路层的几个协议中最简单的协议,是数据链路层各种协议的基础。

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

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

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

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

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

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

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

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

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

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

2.2 帧的结构:

       

帧的类型帧的序号帧的确认号数据信息(可变)校验位

帧的结构

帧的类型(frame_kind):

分为数据帧(data_frame),确认帧(ack_frame)和否认帧(nak_frame)三种。

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

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

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

帧的序号(seq):

由于采用的是单工通信,帧的结构中用的控制域也很少,这个域会随着帧类型的不同而不同:

对数据帧来说:

序号(seq)表示的是发送端发送的帧的序号。

对确认帧来说:

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

对否认帧来说:

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

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

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

2.3 停等协议中相关事件的介绍

帧丢失:

有时,链路上的干扰很严重,或者由于其他的一些原因,接收方收不到发送方发送过来的数据帧,这种情况称为数据帧丢失。

发生数据帧丢失时,接收方自然不会向发送方发送任何应答帧。

如果发送方要等收到收方的应答信息后再发送下一个数据帧,那么双方将永远等下去,这样就出现了死锁现象。

为了解决这个问题,可在发送方发送完一个数据帧后,就启动一个超时定时器。

若到了超时定时器所设置的重发时间tout仍收不到收方的任何应答帧,发送方的计时器发生超时,则发送方就重传前面所发送的这一数据帧。

如果在重传时间tout内收到确认信息,则将超时定时器清零并停止计时。

tout一般的时间设置为略大于“从发完数据帧到收到确认帧所需的平均时间”。

帧重复:

若丢失的是应答帧,则超时重发将会使接收方收到两个同样的数据帧。

由于接收方无法识别重复的数据帧,因而在接收方收到的数据中出现了一种接收序号差错,称为重复帧。

要解决这个问题,必须使每一个数据帧带上不同的发送序号。

若接收方收到序号相同的数据帧,就表明出现了重复帧。

这时接收方应当丢弃这个重复帧。

应该注意到,虽然接收方收到了重复的帧,但它还必须向发送方发送一个确认帧,因为接收方这时已经知道发送方还没有收到上一次接收方向发送方发过去的确认帧。

大家都知道,任何一个编号系统的序号所占用的比特数是有限的。

因此,经过一段时间,发送序号就会重复。

序号占用的比特数越少,数据传输的额外开销就越少。

对于停等协议,由于每发送一个数据帧就停止等待,因此用一个比特来编号就够了,也就是说序号轮流使用0和1。

帧出错:

数据在传输的过程中,不可能保证100%的正确传输,而错误的数据帧对于接收方来说是没有什么意义的。

为了避免收到错误的数据帧,接收方在收到数据帧后,就会采用一定的机制对收到的数据帧进行校验,当校验数据正确时,会向高层传送该帧,反之,则丢弃该帧,从而对上面的网络层提供了传输的服务。

3.实验内容和步骤

3.1步骤:

  

启动程序

打开“数据链路层实验”文件

找到停止等待协议文件

双击此文件中的两个可执行的程序(server.exe,client.exe)

运行应用程序

服务器端:

在服务器信息-服务器IP中输入运行这个程序的计算机的IP地址;

在端口PORT 中输入端口号,也可以使用默认的端口号4000;

点击“建立服务器” 按钮,使其处于监听状态,直到有连接请求;

客户端:

在输入服务器信息-输入服务器IP中输入想连接的服务器的IP地址;

在输入端口PORT中输入和服务器相同的端口号;

点击“连接到服务器” 按钮,使其和服务器进行连接;

点击“设置链路参数”按钮,对链路中的每个参数进行设置

其中,链路的参数主要有:

输入数据的出错率和丢失率主要是为了模拟现实的网络线路状态的,这两个参数的值确定后,输入数据的正确率也就定下来了;

传输数据的超时时间,是发送端发送完一个数据帧到收到应答帧所需的时间;

重传次数是当通信线路质量不是很好时,发送端在重传一定的次数后,就不在进行重传,而是终止发送数据;

点击“开始发送数据”按钮,在弹出的框中输入要传送的数据,然后单击“确定”,则表示从网络层取到一个包,在数据链路层中,把这个数据包封装成帧,发送到接收方,重复这一步可以不断的从网络层取到要发送数据

如果不想再往接收端发送数据,则点击“END” 按钮,退出应用程序

关闭服务器端的应用程序

注意:

一般的客户机/服务器的运行机制是这样的:

服务器端先打开,然后等待客户端的请求,当客户端发送完数据后,会和服务器端主动断开连接,但客户端和服务器断开的时候,需要向服务器端发送一个特殊的数据帧,以此向服务器端说明客户端的数据已发送完毕,这时服务器端也会向客户端发送一个特殊的响应帧,来说明服务器端已做好了和这一客户端断开的准备。

   本实验采用的是这样的一个机制来实现客户端和服务器端断开连接的:

它采用了停止等待协议中帧的结构中的一些变量来交互断开的信息。

当客户端不再向服务器端发送数据的时候,便向服务器端发送一个具有两位数,且内容都是“1”的数据信息,然后封装成帧,发送到接收端。

当接收端收到这个特殊的帧后,会把向客户端发送确认帧中的校验位中的值置为“111”,表示接收端已经知道客户端要和它断开连接。

当客户端收到接收端发送来的这个确认帧后,便和服务器端断开连接,则点击“END” 按钮,退出应用程序。

3.2基本内容:

通过对链路参数进行不同的设置,仔细观察不同的设置对程序的运行有什么影响?

每发送一个数据帧后,分别观察客户端和服务器端的运行结果,体会停止等待协议采用什么样的机制来发送和接收数据信息的?

根据对链路参数不同的设置,记录停止等待协议中发送端数据帧丢失复、帧错误、超时重传次数等各种情形的发生,以加深协议中数据出错控制,数据重复控制,数据丢失控制及协议对这些情况的处理的理解。

3.3扩展内容:

通过阅读源程序,画出服务器端和客户端的程序流程图

对源程序进行阅读分析,了解程序实现的具体的细节,掌握服务器和客户端传送数据的机制

重点分析等待事件的实现和模拟链路参数的实现

4.实验要求

基本要求

记录实验的基本数据,包括选用的计算机的IP地址、连接的端口号、发送端的参数的设置,超时时间的设置,服务器和客户机双方发送的和接收到的数据

记录实验中对数据丢失率,数据出错率等链路参数的设置和相应的实验的结果

根据接收端收到十六进制的数据帧的信息,把它转换成发送端发送的原始的数据

根据你的机器是发送端还是接收端,填写下面的表格1和表格2:

                            数据表格 1

发送端:

协议名称

服务器IP端口号(PORT)

参数设置

出错率

丢失率

超时时间

重传次数

发送数据

接收信息

                数据表格2

接收端:

协议名称

服务器IP端口号(PORT)

接收数据

发送信息

对实验结果进行分析,分析通信双方的数据帧和应答帧之间的关系

记录停止等待协议中帧丢失、帧重复、帧错误等各种情形的发生,以及协议这些情况的处理

思考题:

如果发送端和接收端的端口号不同,将会出现什么情况,为什么?

扩展要求

在读源程序之后画出程序的流程图

捕获事件是停止等待协议的核心,解释程序中是如何实现捕获事件的

5.程序说明

5.1主要的数据结构介绍:

typedef unsigned int seq_nr; //帧的序号和确认号

// 从网络层得到的包的定义

typedef struct{  

            char data[MAX_PKT];

                  }packet;

//帧类型frame_kind的定义

typedef enum{data,ack,nak} frame_kind;

data表示数据帧,ack表示确认帧,nak表示否认帧

//事件的类型的定义

typedef enum{frame_arrival,cksum_err,time_out,nothing} event_type;

//帧结构的定义

typedef struct{

  frame_kind kind; //帧的类型

  seq_nr seq;      //序号

  seq_nr ack;      //确认数

  packet info;     //网络层数据

  int checksum;    //校验域

}frame;

5.2 主要函数介绍:

求校验和:

在构造数据帧的时候用于求出帧的校验域

  int  checksum_mat(packet p);

参数P是要校验的数据包,返回结果是求得的校验域的值。

校验的机制是采用的是输入数据的相加和的方法,也说是把要输入的数据的ASCII值相加,当数据达到1000位的整数位时,再把这个值整除10000作为校验位,在帧中发送到接收方

检查效验和

  bool examine_checksum(frame f);

参数f是收到的数据帧,根据f的信息域在接收端重新求出校验域,求校验域的方法与发送方求校验位的方法相同,然后与收到的数据帧中的校验域进行比较,如果相同则说明收到的数据帧是正确的,则返回true,否则返回false。

从网络层取一个数据和将数据发送到网络层

  void from_network_layer(packet *p);

void to_network_layer(packet p);

为了体现TCP/IP中链路层和网络层的层次性,本实验将取数据和上交数据分别写为一个函数,具体实现的时候用主机来模拟网络层,从网络层取数据直接从键盘或文件取到一个数据包放到p中,然后在数据链路层封装成帧,再发送到物理层;向网络层上交数据直接将接收到的数据在屏幕上输出或写入文件中。

从物理层取数据和向物理层发数据

  int  from_physical_layer(SOCKET sock,frame &r);

  void to_physical_layer(SOCKET sock,frame &s ,int wp,int lp );

为了体现TCP/IP中链路层和物理层的层次性,本实验将接收到的数据和发送的数据也分别写成了一个函数。

接收数据函数从sock接收一个数据帧放到r中,返回取到的字符个数;向物理层发送数据是将帧s从sock发送出去。

对发送数据和接收数据的过程中,数据链路中出现的帧出错、帧重复、帧丢失等各种情况的模拟是在发送端实现的,所以设置了链路质量参数int wp,int lp。

其中,wp表示为发送的数据帧的wrong percent(出错率),lp表示为帧的 lost percent(丢失率)。

这个函数要调用下面介绍的send_frame()函数。

发送一个数据帧,控制发送,模拟链路质量

  void send_frame(SOCKET sock,frame s, int wp,int lp);

sock是发送数据用的套接口,s是要发送的帧, int wp,int lp这两个参数表示要模拟的链路质量参数。

此函数并不在主程序中调用,在而是to_physical_layer(SOCKET sock,frame &s, int wp,int lp)中被调用。

用它来调用winsock中的send()函数。

    根据用户输入的各个参数,当模拟出错时,程序会显示出一个发送的数据帧出错的消息,接收端根据校验会测出收到的数据有错误,给发送端发送一个NAK,这时发送端会重发刚才发送过的一个帧。

    当发送端模拟数据丢失时,程序会显示出一个数据丢失的消息,若到了超时问计时器所设置的重发时间而没有收到接收端发送过来的应答帧,发送端就重传前面所发送的这一个数据帧,从而避免了死锁问题。

等待一个事件发生,返回事件类型

  void wait_for_event(SOCKET sock,event_type &event,int timenum);

此函数的核心是调用select()函数,如果在指定的timenum时间内sock不可读则返回超时事件,否则返回数据到达事件。

5.3 重点和难点介绍:

模拟链路参数

这个实验是在局域网的通信情况下进行实验的,现在的网络无论是局域网还是广域网,数据的丢失率和出错率都很小,但本实验为了充分演示停止-等待协议中对各种可能出现的数据通信情况的处理,采用在发送端设置链路参数的方法来模拟链路中各种可能出现的情况。

对链路参数的模拟是整个程序的核心,本实验中的send_frame()函数就是实现这种模拟功能的,我们具体的介绍一下我们是如何模拟的。

假设设置的链路参数为wp,lp。

在程序运行时,首先产生一个随机数,然后将其转换位某个概率rand,根据rand所属的范围对数据进行处理。

在本实验中根据用户输入的链路参数(这些参数有数据出现错误的百分率,数据丢失的百分率),用户输入错误率和丢失率后,正确的百分率就出来了。

它们共同组成一个百分比,我们就是根据用户输入的这些数据来对链路上的各种情况进行了模拟,从而生动的展现了真实性的网络信息通讯。

客户端在发送数据的时候,采用随机函数randnum(100)产生一个0到99的整数randnumber,然后根据用户输入的参数和产生的随机数来对各种事件进行了模拟:

一般数据传输的过程中,出错和丢失的机率是很少的,所以,把出错率和丢失率分布在0-100这个比率范围的两端,剩下的就是传输数据的正确率了。

如果用户输入的数据的错误率为wp,randnumber/100∈[0,wp),则就认为发生了“帧错误”事件,这是会把客户凋所发送的数据中的某一部分的值修改一下,发送到服务器端,从而模拟了数据通信中的帧错误事件。

如果用户输入的数据的错误率为lp,如果randnumber/100∈[100-wp ,100),就模拟发生了“帧丢失”事件,这时客户端会等待服务器的确认信息,而服务器没有收到信息,就会发生超时事件,当发生超时事件时,客户端会重发上一个数据帧。

剩下的randnumber/100∈[wp ,100-wp)就默认为数据传输的正确率,这时数据帧会正确的发送到接收方。

计时器和数据到达事件的捕获

计时器和数据到达事件的捕获是链路层协议很重要的一部分,wait_event()中主要调用了winsock中的select()函数。

WinSock 编程中有一很方便的地方便是它的消息驱动机制,不管是底层 API 的 WSAAsyncSelect() 还是 MFC 的异步Socket类:

CAsyncSocket,都提供了诸如 FD_ACCEPT、FD_READ、FD_CLOSE 之类的消息供编程人员捕捉并处理。

FD_ACCEPT 通知进程有客户方Socket请求连接,FD_READ通知进程本地Socket有数据可读,FD_CLOSE通知进程对方Socket已关闭。

这些函数都是基于窗口的,但超时计时器和等待事件是停止-等待协议很重要的一部分,在程序的实现中,一个重要的函数就是select()函数,下面简要的介绍一下这个函数。

select()的机制中提供了fd_set的数据结构,实际上是一个long类型的数组,每一个数组元素都能与一个打开的文件句柄(不管是Socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一Socket或文件可读,select()调用返回满足条件的套接字的数目,其调用格式如下:

  

int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

  

下面做一些具体解释:

 

int select(nfds, readfds, writefds, exceptfds, timeout) 

int nfds; 

fd_set *readfds, *writefds, *exceptfds; 

struct timeval *timeout; 

ndfs:

select监视的文件句柄数,它要视进程中打开的文件数而定,一般设为要监视各文件中的最大文件号加一。

 

readfds:

select监视的可读文件句柄集合。

 

writefds:

 select监视的可写文件句柄集合。

 

exceptfds:

select监视的异常文件句柄集合。

 

timeout:

本次select()的超时结束时间。

 

结构timeval的定义为:

strut timeval {

long tv_sec; /* 秒数 */

long tv_usec; /* 微秒数 */

};

当readfds或writefds中映象的文件可读或可写或超时,本次select() 就结束返回。

程序员利用一组系统提供的宏在select()结束时便可判断哪一文件可读或可写。

对Socket编程特别有用的就是readfds。

参数readfds指向要做读检测的套接字描述符集合的指针,调用者希望从中读取数据。

参数writefds 指向要做写检测的套接字描述符集合的指针。

exceptfds指向要检测是否出错的套接字描述符集合的指针。

timeout指向select()函数等待的最大时间,如果设为NULL则为阻塞操作。

select()返回包含在fd_set结构中已准备好的套接字描述符的总数目,或者是发生错误则返回SOCKET_ERROR。

   

几个相关的宏解释如下:

 

FD_ZERO(fd_set *fdset):

清空fdset与所有文件句柄的联系。

 

FD_SET(int fd, fd_set *fdset):

建立文件句柄fd与fdset的联系。

 

FD_CLR(int fd, fd_set *fdset):

清除文件句柄fd与fdset的联系。

 

FD_ISSET(int fd, fdset *fdset):

检查fdset联系的文件句柄fd是否可读写,>0表示可读写。

 

6.参考资料

1.COMPUTER NETRWORKS .计算机网络(第4版).Andrew S.Tanenbaum

2.Internet原理与应用  刘化君 等编著 电子工业出版社

3.计算机网络(第二版),谢希仁 编著 电子工业出版社

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1