1、数据链路层协议的设计与实现计算机通信网络实验 数据链路层协议的设计与实现学院:_20XX11月11日一、实验目的计算机网络的数据链路层协议保证通信双方在有差错的通信线路上进行无差错的数据传输,是计算机网络各层协议中通信控制功能最典型的一种协议。本实验实现一个数据链路层协议的数据传送部分,目的在于更好地理解基本数据链路层协议的基本工作原理,掌握计算机网络协议的基本实现技术。二、实验内容使用C 语言实现下面数据链路层协议:1.分析和实现一个理想的链路层协议2.对于前面实现的协议进行扩充,实现它的第一次改进,如何防止发方过快淹没收方。3.对上一步再假设在不可靠的的链路上进行通信。三、实验步骤1.熟悉
2、数据链路层协议的功能;2.编写数据链路层协议的实现程序;3.调试并运行自己编写的协议实现程序;4.了解协议的工作轨迹,如出现异常情况,在实验报告中写出原因分析;5.保留你实现的数据链路层协议,以备教师检查。四、实验过程1、程序功能及设计思路功能概述:用客户端/服务器模式代表A站、B站。先由客户端输入服务器IP地址,发送SYN同步帧,告诉服务器准备接受。客户端输入数据后,会进行CRC编码,再发送数据帧;服务器收到后,先进行校验,数据正确则发送ACK帧,客户端则发送下一帧数据;否则服务器发送NAK帧,客户端重新发送该数据。CRC校验:1)将收到的字符转为int型32位,并将其二进制码左移16位,存
3、于data;2)进行C=RemainderSDL/g ,即CRC校验,得到校验位。3)将校验位加在信息元后,组成24位的码字,存于要发送的数据帧dframe。停等式ARQ协议:Client: 1)置SN=0;2)收到数据,将SN分配给该数据,如果没有收到,则等待;3)存于要发送的数据帧中,发送给server;4)如果从server收到确认帧,且RNSN,则SN加1模2,返回2;如果收到NAK或RN=SN,则返回3,重传数据。Server:1)置RN=0;2)从client收到一个SN=RN的帧,进行CRC校验检查,无错后输出,并置RN加1、发送ACK帧;否则发送NAK帧,请求重发。 2、C语言
4、程序代码:客户端Client:/* client.c *#include /WINSOCK API的头文件,需要包含在项目中#pragma comment /WINSOCK API连接库文件#include#includeint err;SOCKET sock; /用于服务器监听的SocketSOCKADDR_IN addrSrv; /服务端地址unsigned char sendBuf100; /发送缓存char serverIp20; /客户端ip地址int socklen=sizeof; /Socket的地址值的长度int cf_len=sizeof;struct dataFrame /
5、数据帧 int seq; /分段消息的序号 int SN; /发送序号 unsigned int data100; int msglen; /字符长度,采用长度计数的组帧技术;struct conFrame /控制帧 int RN; /接收序号 char type3; /表明帧的类型:SYN同步、EOT送毕、ACK确认应答、NCK否定应答;struct dataFrame dframe;struct conFrame cframe;/* 初始化*void initialization WORD wVersionRequested; WSADATA wsaData; wVersionReques
6、ted = MAKEWORD; /WinSocket1.1版本 err = WSAStartup; /wsaData用来存储系统传回的关于WinSocket的资料 if LOBYTE != 1 | HIBYTE != 1 WSACleanup; return;/* 计算CRC-16*/基于32位系统,int型长度为4字节,CRC-16的生成多项式为g=D16+D15+D2+1void caculate_crc16 unsigned int data=0; int i,j; / char s32; /用于测试时显示二进制码 fori=0;i data=*msg; / itoa; /把整数转为二进
7、制码 / printf; /test *crc=data16; forj=0;j if data=data&0xffff; data=data0x8005; else data=data&0xffff; *crc=*crc|data; /把校验位放在信息元后面,存在一个int变量中 / itoa; / printf; /test /*发送数据帧*void SendFrame/建立socket,SOCK_DGRAM为使用不连续不可靠的数据包连接 sock=socket; if printf; return; printf;scanf; /输入服务器ip addrSrv.sin_addr.S_un
8、.S_addr=inet_addr; /设置服务器地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons; / 设置服务器端口号 strcpy;cframe.RN=0;/发送同步消息 sendtosock,&cframe,sizeof+1,0,&addrSrv,socklen; printf; dframe.seq=0; while memsetsendBuf,0,sizeof; /清空缓冲区 printf; /输入message,若输入exit则停止发送 scanf; ifstrcmp=0 /当客户端要断开连接时,给服务器发送EOT送毕控制
9、帧strcpy;/发送EOT消息sendtosock,&cframe,sizeof+1,0,&addrSrv,socklen; printf; break; dframe.seq+; dframe.SN=dframe.seq%2; dframe.msglen=strlen; caculate_crc16;/发送消息 sendtosock,&dframe,sizeof,0,&addrSrv,socklen; while recvfromsock,&cframe,sizeof,0,&addrSrv,&cf_len; /接受来自服务器的应答帧 ifstrcmp=0 /如果收到ACK应答指令,则发送下
10、一个message if printf; break; else ifstrcmp=0| printf; sendtosock,&dframe,sizeof,0,&addrSrv,socklen; /重发该消息 closesocket; /关闭连接 return;void main initialization; /初始化阶段,若返回值err=0,则表示初始化成功 if printf; exit; SendFrame; WSACleanup;/* end of program *服务器Server:/* server.c *#include /WINSOCK API的头文件,需要包含在项目中#
11、pragma comment /WINSOCK API连接库文件#include#includeint err;SOCKET sock; /用于服务器监听的SocketSOCKADDR_IN addrSrv; /服务端地址SOCKADDR_IN addrClient; /客户端地址unsigned char recvBuf100; /接受缓存int cf_len=sizeof; /实际存储在recvBuf的地址的长度int socklen=sizeof; /Socket的地址值的长度struct dataFrame /数据帧 int seq; /分段消息的序号 int SN; /发送序号 un
12、signed int data100; int msglen; /字符长度,采用长度计数的组帧技术;struct conFrame /控制帧 int RN; /接收序号 char type3; /表明帧的类型:SYN同步、EOT送毕、ACK确认应答、NCK否定应答;struct dataFrame dframe;struct conFrame cframe; /* 初始化*void initialization WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD; /WinSocket1.
13、1版本 err = WSAStartup; /wsaData用来存储系统传回的关于WinSocket的资料 if LOBYTE != 1 | HIBYTE != 1 WSACleanup; return;/* 绑定端口 *void bindport addrSrv.sin_addr.S_un.S_addr=htonl; /设置服务器地址,INADDR_ANY表示使用自己的IP地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons; /设定端口为6000 err=bindsock,&addrSrv,sizeof; return;/* CRC校验
14、 *void checkout int i,j; unsigned int temp; unsigned int data; unsigned char *msg=recvBuf; /*msg指向recvBuf的首地址 / unsigned char s32; /用于测试时显示二进制码 fori=0;i data=*pdata; temp=16; /将校验位清零,使信息位移到低8位 *msg=temp; / itoa; /把整数转为二进制码 /test / printf; /test forj=0;j /有16位校验元,故循环操作16次,使得到RemainderR/g if data=data
15、&0xffffff; data=data0x800500; else data=data&0xffffff; if strcpy; /若RemainderR/g=0,表示接收序列无误 else strcpy; /若RemainderR/g!=0,表示接收序列有误 return; pdata+; return ;/* 发送及接受消息 *void RecvFrame printf; while recvfromsock,&cframe,sizeof,0,&addrClient,&cf_len; /接受来自客户端的同步帧 ifstrcmp=0 printf-connect with %s.-n,in
16、et_ntoa; break; while cf_len=sizeof; memsetrecvBuf,0,sizeof; /清空接收缓冲区 err=recvfromsock,&dframe,sizeof,0,&addrClient,&cf_len; /接受来自客户端的数据帧 if /当客户端关闭socket时,发送过来的数据会使err=9,则服务器也关闭socket printf; break; checkout; /调用checkout函数,CRC检验接收消息是否正确 ifstrcmp=0 printf; printf; cframe.RN=%2; else ifstrcmp=0 cfram
17、e.RN=dframe.SN; printf; sendtosock,&cframe,sizeof,0,&addrClient,socklen; /发送ACK帧或NAK帧 printf; return;void main initialization; /初始化阶段,若返回值err=0,则表示初始化成功 if printf; return; sock=socket; /建立socket,SOCK_DGRAM为使用不连续不可靠的数据包连接 if printf; return; bindport; /绑定端口 if printf; return; RecvFrame; /接受客户端发送数据 clo
18、sesocket; /关闭连接 WSACleanup;/* end of program *3、实验结果测试1:在没有传输错误情况下,在dos界面显示的传递内容的二进制码和CRC校验码Client: 222.25.162.196,发送数据yl,显示message is delivered successfully后关闭连接。Server: 222.25.162.196,收到数据yl,与上图对比,码字正确,则正确输出数据。测试2:在传输出错情况下,在dos界面显示传递内容的二进制码和CRC校验码Client:222.25.162.196,发送数据yl,传输出错收到NAK后重传数据。Server:222.25.162.196,与上图的二进制码对比发现,第2个码字最后1一位出错,程序显示message is wrong,然后等待客户端重传。通信测试:在dos界面进行通信,但隐藏了二进制码、校验码,实现的是数据的透明传输。Client:Server:222.25.162.196 分析:从上面两图可以看出,服务端和客户端可以实现通畅且准确无误的通信,基本能够实现预期功能。五、实验心得通过本次实验,对数据链路层中数据帧的传输和CRC校验有了更深的了解,不仅仅是停留在书本的理论上了,而且自己对网络编程也有了更大的兴趣。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1