数据链路层协议的设计与实现.docx
《数据链路层协议的设计与实现.docx》由会员分享,可在线阅读,更多相关《数据链路层协议的设计与实现.docx(14页珍藏版)》请在冰豆网上搜索。
![数据链路层协议的设计与实现.docx](https://file1.bdocx.com/fileroot1/2022-11/15/ad59edb8-2e9d-41b5-a47c-6e1554d2175c/ad59edb8-2e9d-41b5-a47c-6e1554d2175c1.gif)
数据链路层协议的设计与实现
计算机通信网络实验
数据链路层协议的设计与实现
学院:
班级:
学号:
:
2012年11月11日
一、实验目的
计算机网络的数据链路层协议保证通信双方在有差错的通信线路上进行无差错的数据传输,是计算机网络各层协议信控制功能最典型的一种协议。
本实验实现一个数据链路层协议的数据传送部分,目的在于更好地理解基本数据链路层协议的基本工作原理,掌握计算机网络协议的基本实现技术。
二、实验容
使用C语言实现下面数据链路层协议:
1.分析和实现一个理想的链路层协议
2.对于前面实现的协议进行扩充,实现它的第一次改进,如何防止发方过快淹没收方。
3.对上一步再假设在不可靠的的链路上进行通信。
三、实验步骤
1.熟悉数据链路层协议的功能;
2.编写数据链路层协议的实现程序;
3.调试并运行自己编写的协议实现程序;
4.了解协议的工作轨迹,如出现异常情况,在实验报告中写出原因分析;
5.保留你实现的数据链路层协议,以备教师检查。
四、实验过程
1、程序功能及设计思路
功能概述:
用客户端/服务器模式代表A站、B站。
先由客户端输入服务器IP地址,发送SYN同步帧,告诉服务器准备接受。
客户端输入数据后,会进行CRC编码,再发送数据帧;服务器收到后,先进行校验,数据正确则发送ACK帧,客户端则发送下一帧数据;否则服务器发送NAK帧,客户端重新发送该数据。
CRC校验:
1)将收到的字符转为int型(32位),并将其二进制码左移16位,存于data;
2)进行C(D)=Remainder[(S(D)∙D^L)/g(D)],即CRC校验,得到校验位。
3)将校验位加在信息元后,组成24位的码字,存于要发送的数据帧dframe。
停等式ARQ协议:
Client:
1)置SN=0;
2)收到数据,将SN分配给该数据,如果没有收到,则等待;
3)存于要发送的数据帧中,发送给server;
4)如果从server收到确认帧,且RN>SN,则SN加1(模2),返回2;如果收到NAK或RN=SN,则返回3,重传数据。
Server:
1)置RN=0;
2)从client收到一个SN=RN的帧,进行CRC校验检查,无错后输出,并置RN加1、发送ACK帧;否则发送NAK帧,请求重发。
2、C语言程序代码:
客户端Client:
//***********************client.c*****************************
#include//WINSOCKAPI的头文件,需要包含在项目中
#pragmacomment(lib,"ws2_32.lib")//WINSOCKAPI连接库文件
#include
#include
interr;
SOCKETsock;//用于服务器监听的Socket
SOCKADDR_INaddrSrv;//服务端地址
unsignedcharsendBuf[100];//发送缓存
charserverIp[20];//客户端ip地址
intsocklen=sizeof(SOCKADDR_IN);//Socket的地址值的长度
intcf_len=sizeof(structsockaddr);
structdataFrame//数据帧
{
intseq;//分段消息的序号
intSN;//发送序号
unsignedintdata[100];
intmsglen;//字符长度,采用长度计数的组帧技术
};
structconFrame//控制帧
{
intRN;//接收序号
chartype[3];
//表明帧的类型:
SYN同步、EOT送毕、ACK确认应答、NCK否定应答
};
structdataFramedframe;
structconFramecframe;
//************************初始化******************************
voidinitialization()
{
WORDwVersionRequested;
WSADATAwsaData;
wVersionRequested=MAKEWORD(1,1);//WinSocket1.1版本
err=WSAStartup(wVersionRequested,&wsaData);
//wsaData用来存储系统传回的关于WinSocket的资料
if(LOBYTE(wsaData.wVersion)!
=1||HIBYTE(wsaData.wVersion)!
=1){
WSACleanup();
}
return;
}
//************************计算CRC-16******************************
//基于32位系统,int型长度为4字节,CRC-16的生成多项式为g(D)=D^16+D^15+D^2+1
voidcaculate_crc16(unsignedchar*msg,intlenth,unsignedint*crc)
{
unsignedintdata=0;
inti,j;
//chars[32];//用于测试时显示二进制码
for(i=0;idata=(int)*msg;
//itoa(data,s,2);//把整数转为二进制码
//printf("第%d字的二进制码:
%s\n",i+1,s);//test
*crc=data<<16;
for(j=0;j<16;j++)
{
if((data&0x8000))
{
data=(data<<1)&0xffff;
data=data^0x8005;
}
elsedata=(data<<1)&0xffff;
}
*crc=*crc|data;//把校验位放在信息元后面,存在一个int变量中
//itoa(*crc,s,2);
//printf("加上CRC校验位后的二进制码:
%s\n",s);//test
}
}
//************************发送数据帧******************************
voidSendFrame(){
//建立socket,SOCK_DGRAM为使用不连续不可靠的数据包连接
sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock==-1){
printf("Buildingasocketfailed.\n");
return;
}
printf("inputserver'sIP:
");
scanf("%s",serverIp);//输入服务器ip
addrSrv.sin_addr.S_un.S_addr=inet_addr(serverIp);//设置服务器地址
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);//设置服务器端口号
strcpy(cframe.type,"SYN");
cframe.RN=0;
//发送同步消息
sendto(sock,(char*)&cframe,sizeof(cframe)+1,0,(SOCKADDR*)&addrSrv,socklen);
printf("----------------------------------------------\n");
dframe.seq=0;
while
(1)
{
memset(sendBuf,0,sizeof(sendBuf));//清空缓冲区
printf("Inputthemessage:
");//输入message,若输入exit则停止发送
scanf("%s",sendBuf);
if(strcmp(sendBuf,"exit")==0){
//当客户端要断开连接时,给服务器发送EOT送毕控制帧
strcpy(cframe.type,"EOT");
//发送EOT消息
sendto(sock,(char*)&cframe,sizeof(cframe)+1,0,(SOCKADDR*)&addrSrv,socklen);
printf("------------------closesocket!
-----------------\n");
break;
}
dframe.seq++;
dframe.SN=dframe.seq%2;
dframe.msglen=strlen(sendBuf);
caculate_crc16(sendBuf,dframe.msglen,dframe.data);
//发送消息
sendto(sock,(char*)&dframe,sizeof(structdataFrame),0,(SOCKADDR*)&addrSrv,socklen);
while
(1)
{
recvfrom(sock,(char*)&cframe,sizeof(structconFrame),0,(SOCKADDR*)&addrSrv,&cf_len);//接受来自服务器的应答帧
if(strcmp(cframe.type,"ACK")==0)//如果收到ACK应答指令,则发送下一个message
{
if(cframe.RN!
=dframe.SN){
printf("--------messageisdeliveredsuccessfully.----------\n");
break;
}
}elseif((strcmp(cframe.type,"NAK")==0)|(cframe.RN==dframe.SN))
{
printf("--------messageredeliverring.----------\n");
sendto(sock,(char*)&dframe,sizeof(structdataFrame),0,(SOCKADDR*)&addrSrv,socklen);//重发该消息
}
}
}
closesocket(sock);//关闭连接
return;
}
voidmain(){
initialization();//初始化阶段,若返回值err=0,则表示初始化成功
if(err){
printf("Initializationfalied.\n");
exit(0);
}
SendFrame();
WSACleanup();
}
//**********************endofprogram************************
服务器Server:
//***********************