数据链路层协议的设计与实现Word文档格式.docx
- 文档编号:17706644
- 上传时间:2022-12-08
- 格式:DOCX
- 页数:13
- 大小:18.94KB
数据链路层协议的设计与实现Word文档格式.docx
《数据链路层协议的设计与实现Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据链路层协议的设计与实现Word文档格式.docx(13页珍藏版)》请在冰豆网上搜索。
停等式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<
winsock.h>
//WINSOCKAPI的头文件,需要包含在项目中
#pragmacomment<
lib,"
ws2_32.lib"
>
//WINSOCKAPI连接库文件
stdio.h>
string.h>
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<
=1>
WSACleanup<
}
return;
}
//************************计算CRC-16******************************
//基于32位系统,int型长度为4字节,CRC-16的生成多项式为g<
=D^16+D^15+D^2+1
voidcaculate_crc16<
unsignedchar*msg,intlenth,unsignedint*crc>
unsignedintdata=0;
inti,j;
//chars[32];
//用于测试时显示二进制码
for<
i=0;
i<
lenth;
i++,crc++,msg++>
data=<
int>
*msg;
//itoa<
data,s,2>
//把整数转为二进制码
//printf<
"
第%d字的二进制码:
%s\n"
i+1,s>
//test
*crc=data<
<
16;
j=0;
j<
j++>
{
if<
data&
0x8000>
data<
1>
&
0xffff;
data=data^0x8005;
}
elsedata=<
*crc=*crc|data;
//把校验位放在信息元后面,存在一个int变量中
*crc,s,2>
加上CRC校验位后的二进制码:
s>
//************************发送数据帧******************************
voidSendFrame<
//建立socket,SOCK_DGRAM为使用不连续不可靠的数据包连接
sock=socket<
AF_INET,SOCK_DGRAM,0>
sock==-1>
printf<
Buildingasocketfailed.\n"
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>
----------------------------------------------\n"
dframe.seq=0;
while<
memset<
sendBuf,0,sizeof<
sendBuf>
//清空缓冲区
Inputthemessage:
//输入message,若输入exit则停止发送
scanf<
sendBuf>
strcmp<
sendBuf,"
exit"
==0>
//当客户端要断开连接时,给服务器发送EOT送毕控制帧
strcpy<
EOT"
//发送EOT消息
sendto<
SOCKADDR*>
------------------closesocket!
-----------------\n"
break;
dframe.seq++;
dframe.SN=dframe.seq%2;
dframe.msglen=strlen<
caculate_crc16<
sendBuf,dframe.msglen,dframe.data>
//发送消息
dframe,sizeof<
structdataFrame>
0,<
recvfrom<
structconFrame>
addrSrv,&
cf_len>
//接受来自服务器的应答帧
cframe.type,"
ACK"
//如果收到ACK应答指令,则发送下一个message
cframe.RN!
=dframe.SN>
--------messageisdeliveredsuccessfully.----------\n"
}elseif<
NAK"
|<
cframe.RN==dframe.SN>
--------messageredeliverring.----------\n"
structdataFrame>
//重发该消息
closesocket<
sock>
//关闭连接
voidmain<
initialization<
//初始化阶段,若返回值err=0,则表示初始化成功
err>
Initializationfalied.\n"
exit<
0>
SendFrame<
//**********************endofprogram************************
服务器Server:
//***********************server.c*****************************
SOCKADDR_INaddrClient;
//客户端地址
unsignedcharrecvBuf[100];
//接受缓存
//实际存储在recvBuf的地址的长度
interr;
//************************绑定端口******************************
voidbindport<
addrSrv.sin_addr.S_un.S_addr=htonl<
INADDR_ANY>
//设置服务器地址,INADDR_ANY表示使用自己的IP地址
//设定端口为6000
err=bind<
LPSOCKADDR>
addrSrv,sizeof<
SOCKADDR>
//**********************CRC校验**************************
voidcheckout<
unsignedint*pdata,intlenth>
unsignedinttemp;
unsignedintdata;
unsignedchar*msg=recvBuf;
//*msg指向recvBuf的首地址
//unsignedchars[32];
i++,msg++>
data=*pdata;
temp=<
0xff0000>
//将校验位清零,使信息位移到低8位
*msg=temp;
//把整数转为二进制码//test
收到的二进制码:
//有16位校验元,故循环操作16次,使得到Remainder[R<
x>
]
0x800000>
0xffffff;
data=data^0x800500;
data==0>
//若Remainder[R<
]=0,表示接收序列无误
else{
]!
=0,表示接收序列有误
pdata++;
return;
//**********************发送及接受消息**************************
voidRecvFrame<
--------------------serverwaitting.--------------------\n"
addrClient,&
//接受来自客户端的同步帧
---------connectwith%s.-------\n"
inet_ntoa<
addrClient.sin_addr>
cf_len=sizeof<
recvBuf,0,sizeof<
recvBuf>
//清空接收缓冲区
err=recvfrom<
//接受来自客户端的数据帧
err==9>
//当客户端关闭socket时,发送过来的数据会使err=9,则服务器也关闭socket
---------clientclosethesocket!
-------\n"
checkout<
dframe.data,dframe.msglen>
//调用checkout<
函数,CRC检验接收消息是否正确
client:
recvBuf>
---------messageiscorrect!
cframe.RN=<
dframe.SN+1>
%2;
elseif<
cframe.RN=dframe.SN;
----------messageiswrong!
addrClient,socklen>
//发送ACK帧或NAK帧
--------------------Theend!
------------------\n"
err!
=0>
Intializationfailed.\n"
sock=socket<
//建立socket,SOCK_DGRAM为使用不连续不可靠的数据包连接
bindport<
//绑定端口
Bindingasocketfailed.\n"
RecvFrame<
//接受客户端发送数据
3、实验结果
测试1:
在没有传输错误情况下,在dos界面显示的传递内容的二进制码和CRC校验码
222.25.162.196,发送数据"
yl"
显示"
messageisdeliveredsuccessfully"
后关闭连接。
Server:
222.25.162.196,收到数据"
与上图对比,码字正确,则正确输出数据。
测试2:
在传输出错情况下,在dos界面显示传递内容的二进制码和CRC校验码
Client:
222.25.162.196,发送数据"
传输出错收到NAK后重传数据。
222.25.162.196,与上图的二进制码对比发现,第2个码字最后1一位出错,
程序显示"
messageiswrong"
然后等待客户端重传。
通信测试:
在dos界面进行通信,但隐藏了二进制码、校验码,实现的是数据的透明传输。
222.25.162.196
分析:
从上面两图可以看出,服务端和客户端可以实现通畅且准确无误的通信,基本能够实现预期功能。
五、实验心得
通过本次实验,对数据链路层中数据帧的传输和CRC校验有了更深的了解,不仅仅是停留在书本的理论上了,而且自己对网络编程也有了更大的兴趣。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据链 协议 设计 实现