中南大学通信电子专业通信网原理课程设计.docx
- 文档编号:24011621
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:18
- 大小:82.09KB
中南大学通信电子专业通信网原理课程设计.docx
《中南大学通信电子专业通信网原理课程设计.docx》由会员分享,可在线阅读,更多相关《中南大学通信电子专业通信网原理课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
中南大学通信电子专业通信网原理课程设计
题目名称:
CRC-32校验通信软件设计
一、设计目标
环境要求:
Windows;信息交换内容为文本文件;WinSock通信
编码要求:
用模2除法计算CRC码,生成多项式为CRC-32
功能要求:
能在两台计算机机上运行程序,一台产生CRC码,另一台校验。
二、设计原理和方法
1.CRC简介及原理
CRC,即循环冗余校验法是一种功能较强的检测技术。
循环冗余校验法是将所传输的数据除以一个预先设定的除数,所得的余数作为冗余比特,附加在要发送数据的末尾,被称为循环冗余校验码(CRC码),这样,实际传输的数据就能够被预先设定的除数整除。
当整个数据传送到接收方后,接收方就利用同一个除数去除接收到的数据,如果余数为0,即表明数据传输正确,否则意味着数据传输出现了差错。
确定循环冗余校验码的关键在于二进制序列的除法计算上。
其规则是:
加法、减法运算都是进行异或(XOR)运算,加法不进位,减法不借位。
计算方法如下:
在数据的末尾加上n个0,n等于除数的位数减1;
采用二进制除法规则(模2除法),计算加长的数据除以预先设定的除数,得到的余数即为循环冗余校验码;
将循环冗余校验码替换数据末尾的n个0,即得出整个传输的数据。
CRC-32是CRC的校验标准之一,其除数,即生成多项式为:
g(x)=x32+x26+x23+x22+x16+
x12+x11+x10+x8+x7+x5+x4+x2+x+1,其对应校验二进制为 100000100110000010001110110110111,16进制记为104C11DB7。
按上述规则先将要发送的二进制序列数左移32位后,再除以多项式g(x),最后得到的余数即是CRC-32码。
将CRC-32码替换发送数据末尾的32个0,得到整个传输数据。
接在收端收到整个传输数据,将数据除以多项式g(x),若余数为0,则传输正确,去掉后32位即得到需要的数据;若信道有干扰,除以多项式g(x)后余数不为0,则传输失败,等待重传。
2.模2除法计算CRC码的方法
通常的CRC算法是模仿硬件的算法,在计算一个数据段的CRC值时,其CRC值是由求解每个数值的CRC值的和对CRC寄存器的值反复更新而得到的。
假设待测数据是1101011011,生成项是10011,假设有一个4bits的寄存器,通过反复的移位和进行CRC的除法,最终该寄存器中的值就是我们所要求的余数。
3210Bits
+---+---+---+---+
Pop<--|||||<-----Augmentedmessage(已加0扩张的原始数据)
+---+---+---+---+
10011=ThePoly生成项
依据这个模型,我们得到了一个最最简单的算法:
把register中的值置0.
把原始的数据后添加w个0.
While(还有剩余没有处理的数据)
Begin
把register中的值左移一位,读入一个新的数据并置于register最低位的位置。
If(如果上一步的左移操作中的移出的一位是1)
register=registerXORPoly.
End
实际上就是模拟XOR除法的过程,即被测数据一位一位放到寄存器中来做除法。
比如生成项是10011,则生成的余数是4位XXXX,所以寄存器是4位。
待测数据是1101011011,后面加上0000,即扩张4位,以容纳余数。
只要与生成项的0011做XOR就好了,最高位经过XOR肯定出0,可不用最高位。
3.Winsock通信的原理
套接字(Socket)是网络通信的基本构件。
套接字是可以被命名的通信端点,应用程序通过它在网络上发送和接收数据。
每个套接字都有其类型,并有一个与之相连的进程。
TCP/IP提供3种类型套接字:
流式套接字(SOCK—STREAM)、数据包套接字(SOCK—DGRAM)、原始式套接字(SOCK—RAW)。
流式套接字(SOCK—STREAM)提供一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。
内设流量控制,避免数据流超限;数据被看作字节流,无长度限制。
流式套接字提供了一种可靠的面向连接的数据传输方式,如果想发送大批量数据或想让数据按顺序无重复地到达目的地,流式套接字最为有用。
本文使用流式套接字。
通过一个客户机/服务器模式的网络应用程序,实现对CSocket类的派生和应用为例介绍网络通信的实现。
数据集中管理需要融合各控制系统的不同数据,由于各控制系统连接在不同的网络上,要融合其中的实时信息需要解决异种网联的问题,而TCP/IP协议无疑是一个很好的选择。
对于各集中监测系统,与数据集中管理系统同在中央调度室,因此可以在遵循TCP/IP协议的局域网中进行实时通信。
在TCP/IP协议下利用Socket进行网络编程,自然就会涉及到C/S(客户机/服务器)模式,即客户端向服务器发出请求,服务器接收到请求后提供相应的服务。
客户机/服务器模式在操作过程中采取的是主动请求方式。
三、设计功能
本次实验在VC++环境下实现。
发送端:
通过键盘键入信息,对键入的信息进行CRC-32编码,将加入CRC编码的信息通过Winsock传送给接收端。
接收端:
通过Winsock监听到发送端,接收信息。
对接收到的信息进行校验,除以对应的生成项并判断余数是否为0。
余数为0则显示传输成功,否则显示传输失败。
模拟出错情况,改变传输的信息内容,测试程序校验功能。
四、程序框图
1.总程序流程图
发送端(电脑A)---------文本文件传输----------接收端(电脑B)
图4.1总程序流程图
2.基于Winsock的客户机/服务器应用程序基本结构
服务器方(接收端)
初始化本地端口,用Socket创建本地端口
绑定本地端口,用Bind()指定本地地址
倾听此端口,Listen()监听连接
客户方(发送端)
初始化本地端口用Socket创建本地端口1
接收请求,用Accept()接收请求
连接服务器端口,用Connect()连接
阻塞、等待客户请求
发送请求数据,用Send()发送
在此连接端口接受传输数据,用Receive()
在此连接端接受传输数据,用Receive()
发送响应数据,用Send()
断开连接,用Close()关闭端口
断开连接,用Close()关闭端口
结束服务
图4.2Winsock通信基本结构
五、程序清单
1.发送端电脑A源程序
#include
#include
#include
#include
#pragmacomment(lib,"Ws2_32.lib")
__int64crc;//定义全局变量crc
__int64create(__int64data,__int64POLY,intcrcbitnumber)//生成crc码子函数
{
__int64regi=0x0;//使寄存器为0
__int64data_temp;
data_temp=data;
intdatabitnumber=32;//定义数据位数,即输入的十六进制数最多8位
data<<=crcbitnumber;//data左移32位即在数据位后添加32个0
for(intcur_bit=databitnumber+crcbitnumber-1;cur_bit>=0;--cur_bit)//处理64次(32比特待测数据+32比特扩展0),前32次是加载32比特待测数据,后32次是加载一比特扩展0
{
if(((regi>>crcbitnumber)&0x0001)==0x1)regi=regi^POLY;
regi<<=1;
unsignedshorttmp=(data>>cur_bit)&0x0001;//加载待测数据1比特到tmp中,tmp只有1比特
regi|=tmp;//这1比特加载到寄存器中
}
if(((regi>>crcbitnumber)&0x0001)==0x1)
regi=regi^POLY;//做最后一次XOR
printf("\t\t\tcrc=%I64d\n",regi);
crc=regi;
data_temp<<=32;
data_temp=data_temp+regi;
returndata_temp;
}
voidSend(__int64code)
{
WORDwVersionRequested;
WSADATAwsaData;
interr;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!
=0)
{
return;
}
if(LOBYTE(wsaData.wVersion)!
=2||
HIBYTE(wsaData.wVersion)!
=2)
{
WSACleanup();
return;
}
SOCKETsocketClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_INaddrSrv;
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//服务器端的IP地址
connect(socketClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
charrecvBuf[256];
charsendBuf[100];
recv(socketClient,recvBuf,256,0);
sprintf(sendBuf,"%I64x",code);
send(socketClient,sendBuf,strlen(sendBuf)+1,0);
closesocket(socketClient);
WSACleanup();
}
intmain()
{
__int64code;//code即为实际传输的数据
__int64data;//data为从键盘输入的数据即要传输的数据
__int64POLY=(__int64)0x254028D1*0x7;
intcrcbitnumber=32;
printf("\n\t\t**************CRC校验发送端**************\n\n");
while
(1)
{
printf("\t\t\t请输入需要传输的数据:
");
scanf("%I64x",&data);//%x,输入16进制整数
code=create(data,POLY,crcbitnumber);
printf("\t\t\tCODE=%I64x\n\n",code);
Send(code);
}
getchar();
}
2.接收端电脑B源程序
#include
#include
#include
#pragmacomment(lib,"WS2_32.lib")
__int64exam(__int64data,__int64POLY,intcrcbitnumber)
{
__int64regi=0x0;
__int64data_temp;
data_temp=data;
intdatabitnumber=32;
for(intcur_bit=databitnumber+crcbitnumber-1;cur_bit>=0;--cur_bit)
{
if(((regi>>crcbitnumber)&0x0001)==0x1)
regi=regi^POLY;
regi<<=1;
unsignedshorttmp=(data>>cur_bit)&0x0001;
regi|=tmp;
}
if(((regi>>crcbitnumber)&0x0001)==0x1)
regi=regi^POLY;
return(regi);
}
voidSolve(__int64code)
{
__int64result;
__int64POLY=(__int64)0x254028D1*0x7;
intcrcbitnumber=32;
printf("\n\t\t**************CRC校验接收端**************\n\n");
printf("\t\t\tcode=%I64x\n\n",code);
result=exam(code,POLY,crcbitnumber);
printf("\t\t\tresult=%I64x,",result);
if(result==0)
{
printf("数据传输正确!
\n\n");
code>>=32;
printf("\t\t\t去除CRC校验码后数据是%I64x。
\n\n",code);
}
elseprintf("\n\t\t\t数据传输失败。
");
}
intmain()
{
__int64code;
WORDwVersionRequested;//版本号
WSADATAwsaData;
interr;
printf("\n\t\t**************winsocket服务端**************\n\n");
wVersionRequested=MAKEWORD(2,2);//2.2版本的套接字
//加载套接字库,如果失败返回
err=WSAStartup(wVersionRequested,&wsaData);
if(err!
=0)
{
return0;
}
//判断高低字节是不是2,如果不是2.2的版本则退出
if(LOBYTE(wsaData.wVersion)!
=2||
HIBYTE(wsaData.wVersion)!
=2)
{
return0;
}
//创建流式套接字,基于TCP(SOCK_STREAM)
SOCKETsocSrv=socket(AF_INET,SOCK_STREAM,0);
//Socket地址结构体的创建
SOCKADDR_INaddrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//转换Unsignedlong型为网络字节序格
addrSrv.sin_family=AF_INET;//指定地址簇
addrSrv.sin_port=htons(6000);
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
//将套接字绑定到一个端口号和本地地址上
bind(socSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//必须用sizeof,strlen不行
listen(socSrv,5);
SOCKADDR_INaddrClient;//字义用来接收客户端Socket的结构体
intlen=sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
//循环等待接受客户端发送请求
while
(1)
{
//等待客户请求到来;当请求到来后,接受连接请求,
//返回一个新的对应于此次连接的套接字(accept)。
//此时程序在此发生阻塞
SOCKETsockConn=accept(socSrv,(SOCKADDR*)&addrClient,&len);
charsendBuf[100];
sprintf(sendBuf,"Welcome%stoCSU",
inet_ntoa(addrClient.sin_addr));//格式化输出
//用返回的套接字和客户端进行通信
send(sockConn,sendBuf,strlen(sendBuf)+1,0);//多发送一个字节
//接收数据
charrecvBuf[100];
recv(sockConn,recvBuf,100,0);
closesocket(sockConn);
sscanf(recvBuf,"%I64x",&code);
Solve(code);
}
}
六、测试数据及结果
1.测试数据正确时
发送端:
图6.1发送端
(1)
接收端:
图6.2接收端
(1)
说明:
其中,显示的crc为411981648是十进制表示,转换为16进制,即为CODE中信息后缀内容188e5750。
余数result的结果为0,数据传输正确。
2.测试数据溢出时
发送端:
图6.3发送端
(2)
接收端:
图6.4接收端
(2)
说明:
发送9位16进制信息时,由于code最多为16位16进制,且crc32码为8位16进制数,所以溢出信息的1位最高位。
3.测试数据传输失败时
发送端:
图6.5发送端(3)
接收端:
图6.6接收端(3)
说明:
模拟传输出错情况,改变接收端接收到的数据内容,校验时余数result不为0,所以传输失败。
七、总结
1.课设过程中遇到的问题及解决方案
课设中遇到的第一个难题是数据位数的问题。
int只有4字节,而CRC-32的生成项的二进制形式为33位,在原有信息后面再加上33位后,超出了定义范围。
后经过查找资料发现,__int64可以表示8个字节,即64位,可以满足要求。
但是,VC的输入输出与__int64的兼容就不是很好,会产生错误提示“ nooperatordefinedwhichtakesaright-handoperandoftype'__int64' ”。
此时使用C的写法:
scanf("%I64d",&a)和printf("%I64d",a),就可以正确输入输出了。
课设过程中遇到的第二个大难题是生成项0x104C11DB7超出范围,和同学讨论后确定是电脑机器位数不够造成的,可以进行强制转换,经过各种尝试,最终确定强制转换类型为:
__int64POLY=(__int64)0x254028D1*0x7,其中0x254028D1*0x7=0x104C11DB7。
课设中遇到的第三个难题简直是灾难性的,那就是在第一次检查过程中才发现看错了题目条件,将Winsock通信的题目,看错是共享文件通信,所以之前在实验时都是通过共享文件实现通信信息交换。
但是人的潜力是无穷的,虽然时间紧迫,最后我还是结合在网上查找的Winsock通信代码资料,顺利将自己的代码改写完成。
并且在学习通信网的课程时进行的实验,也做过关于socket通信的相关实验,所以我对于socket的基本原理还是比较清楚的,因此这方面的代码上手比较快,加快了自己代码完成的进程。
2.课程成果反思
我所采用的CRC代码算法是模仿硬件的算法,在计算一个数据段的CRC值时,其CRC值是由求解每个数值的CRC值的和对CRC寄存器的值反复更新而得到的。
但是这种算法求CRC的速度较慢,还有一种算法可以通过查表来快速完成,叫做“驱动表法”算法。
对于“驱动表法”可以再多多思考
另外,我是通过直接修改代码中计算公式来模拟传输出错的,其实也可以在代码中多加入一个模拟出错模块,做一个选项,选择随机位数差错或者突发差错,为传输信息提供随机变化,再通过计算校验传输是否正确。
3.心得体会
这次课设让我受益匪浅,不仅让我对于CRC码算法和模2除法的原理有了透彻的理解,还让我重温了socket通信的算法。
CRC校验码的用途很多,例如CRC-32就应用在ZIP,RAR,IEEE802LAN/FDDI,IEEE1394,PPP-FCS等多个方面。
socket通信也让我对于TCP/IP协议有了更加深入的理解。
另外再次锻炼了我的C语言编程能力,也提醒我要更加注重细节,常言道细节决定成败,在编程这块这是真理。
除却在专业知识上有了更加深入的理解,我也感受到了王老师培养学生能力的拳拳之心。
感谢王老师的教育及督促,今后一定会更加努力提升自己的专业技能。
八、参考资料
[1]施荣华,王国才.《计算机通信网络技术及应用》.中国水利水电出版社2012年
[2]高传善等编著.数据通信与计算机网络,高等教育出版社,2004年
[3]INTERNET相关资料
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中南 大学 通信 电子 专业 通信网 原理 课程设计