中南大学通信电子专业通信网原理课程设计.doc_第1页
中南大学通信电子专业通信网原理课程设计.doc_第2页
中南大学通信电子专业通信网原理课程设计.doc_第3页
中南大学通信电子专业通信网原理课程设计.doc_第4页
中南大学通信电子专业通信网原理课程设计.doc_第5页
已阅读5页,还剩5页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

通信网原理课程设计 题号:C8题目名称: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,其对应校验二进制为1 0000 0100 1100 0001 0001 1101 1011 0111,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,假设有一个4 bits的寄存器,通过反复的移位和进行CRC的除法,最终该寄存器中的值就是我们所要求的余数。 3 2 1 0 Bits +-+-+-+-+ Pop - | | | | | - Augmented message(已加0扩张的原始数据) +-+-+-+-+ 1 0 0 1 1 = The Poly 生成项依据这个模型,我们得到了一个最最简单的算法:把register中的值置0. 把原始的数据后添加w个0. While (还有剩余没有处理的数据) Begin 把register中的值左移一位,读入一个新的数据并置于register最低位的位置。 If (如果上一步的左移操作中的移出的一位是1) register = register XOR Poly. End 实际上就是模拟XOR除法的过程,即被测数据一位一位放到寄存器中来做除法。比如生成项是10011,则生成的余数是4位XXXX,所以寄存器是4位。待测数据是1101 0110 11,后面加上0000,即扩张4位,以容纳余数。只要与生成项的0011做XOR就好了,最高位经过XOR肯定出0,可不用最高位。3.Winsock通信的原理套接字(Socket)是网络通信的基本构件。套接字是可以被命名的通信端点,应用程序通过它在网络上发送和接收数据。每个套接字都有其类型,并有一个与之相连的进程。TCP/IP提供3种类型套接字:流式套接字(SOCKSTREAM)、数据包套接字(SOCKDGRAM)、原始式套接字(SOCKRAW)。流式套接字(SOCKSTREAM)提供一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。 内设流量控制,避免数据流超限;数据被看作字节流,无长度限制。流式套接字提供了一种可靠的面向连接的数据传输方式,如果想发送大批量数据或想让数据按顺序无重复地到达目的地,流式套接字最为有用。本文使用流式套接字。通过一个客户机/服务器模式的网络应用程序,实现对CSocket类的派生和应用为例介绍网络通信的实现。数据集中管理需要融合各控制系统的不同数据,由于各控制系统连接在不同的网络上,要融合其中的实时信息需要解决异种网联的问题,而TCP/IP协议无疑是一个很好的选择。对于各集中监测系统,与数据集中管理系统同在中央调度室,因此可以在遵循TCP/IP协议的局域网中进行实时通信。 在TCP/IP协议下利用Socket进行网络编程,自然就会涉及到C/S(客户机/服务器)模式,即客户端向服务器发出请求,服务器接收到请求后提供相应的服务。客户机/服务器模式在操作过程中采取的是主动请求方式。三、设计功能 本次实验在VC+环境下实现。发送端:通过键盘键入信息,对键入的信息进行CRC-32编码,将加入CRC编码的信息通过Winsock传送给接收端。接收端:通过Winsock监听到发送端,接收信息。对接收到的信息进行校验,除以对应的生成项并判断余数是否为0。余数为0则显示传输成功,否则显示传输失败。 模拟出错情况,改变传输的信息内容,测试程序校验功能。四、程序框图1.总程序流程图发送端(电脑A) -文本文件传输- 接收端(电脑B)开始开始通过Winsock接收数据输入数据存入code接收的数据模二除多项式g(x)得到余项result计算CRC余项result=0?将CRC余项接在code的后面赋给code传输失败传输正确,显示信息码通过Winsock发送数据到接收端结束结束图4.1 总程序流程图2.基于Winsock的客户机/服务器应用程序基本结构 服务器方(接收端)初始化本地端口,用Socket创建本地端口绑定本地端口,用Bind()指定本地地址 倾听此端口,Listen()监听连接客户方(发送端)初始化本地端口用Socket创建本地端口1接收请求,用Accept()接收请求连接服务器端口,用Connect()连接阻塞、等待客户请求发送请求数据,用Send()发送在此连接端口接受传输数据,用Receive()在此连接端接受传输数据,用Receive()发送响应数据,用Send()断开连接,用Close()关闭端口断开连接,用Close()关闭端口 结束服务图4.2 Winsock通信基本结构五、程序清单1.发送端电脑A源程序#include #include #include #include #pragma comment(lib, Ws2_32.lib)_int64 crc; /定义全局变量crc_int64 create(_int64 data,_int64 POLY,int crcbitnumber) /生成crc码子函数 _int64 regi = 0x0; / 使寄存器为0 _int64 data_temp; data_temp=data; int databitnumber=32; /定义数据位数,即输入的十六进制数最多8位 data= 0; - cur_bit ) /处理64 次(32 比特待测数据32 比特扩展0),前32次是加载32比特待测数据,后32次是加载一比特扩展0 if ( ( ( regi crcbitnumber ) & 0x0001 ) = 0x1 ) regi = regi POLY; regi cur_bit ) & 0x0001; /加载待测数据1比特到tmp中,tmp只有1比特 regi |= tmp; /这1比特加载到寄存器中 if ( ( ( regi crcbitnumber ) & 0x0001 ) = 0x1 ) regi = regi POLY; /做最后一次XOR printf(tttcrc=%I64dn,regi); crc=regi; data_temp=32; data_temp=data_temp+regi; return data_temp;void Send(_int64 code) WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) return ; if ( LOBYTE( wsaData.wVersion ) != 2 | HIBYTE( wsaData.wVersion ) != 2 ) WSACleanup( ); return ; SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; 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); char recvBuf256; char sendBuf100 ; recv(socketClient, recvBuf, 256, 0); sprintf(sendBuf , %I64x , code) ; send(socketClient, sendBuf, strlen(sendBuf) + 1, 0); closesocket(socketClient); WSACleanup();int main() _int64 code;/code即为实际传输的数据 _int64 data;/data为从键盘输入的数据即要传输的数据 _int64 POLY= (_int64)0x254028D1*0x7 ; int crcbitnumber=32; printf(ntt* CRC校验发送端 *nn); while(1) printf(ttt请输入需要传输的数据:); scanf(%I64x,&data);/%x,输入16进制整数 code=create(data,POLY,crcbitnumber); printf(tttCODE=%I64xnn,code); Send(code) ; getchar();2.接收端电脑B源程序#include #include #include #pragma comment(lib, WS2_32.lib)_int64 exam(_int64 data,_int64 POLY,int crcbitnumber) _int64 regi = 0x0; _int64 data_temp; data_temp=data; int databitnumber=32; for ( int cur_bit = databitnumber+crcbitnumber-1; cur_bit = 0; - cur_bit ) if ( ( ( regi crcbitnumber ) & 0x0001 ) = 0x1 ) regi = regi POLY; regi cur_bit ) & 0x0001; regi |= tmp; if ( ( ( regi crcbitnumber ) & 0x0001 ) = 0x1 ) regi = regi POLY; return(regi);void Solve(_int64 code) _int64 result; _int64 POLY=(_int64) 0x254028D1*0x7; int crcbitnumber=32; printf(ntt* CRC校验接收端 *nn); printf(tttcode=%I64xnn,code); result=exam(code,POLY,crcbitnumber); printf(tttresult=%I64x,,result); if (result=0) printf(数据传输正确!nn); code=32; printf(ttt去除CRC校验码后数据是%I64x。nn,code); else printf(nttt数据传输失败。);int main() _int64 code ; WORD wVersionRequested;/版本号 WSADATA wsaData; int err; printf(ntt* winsocket服务端 *nn); wVersionRequested = MAKEWORD(2, 2);/2.2版本的套接字 /加载套接字库,如果失败返回 err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) return 0; /判断高低字节是不是2,如果不是2.2的版本则退出 if (LOBYTE(wsaData.wVersion) != 2 | HIBYTE(wsaData.wVersion) != 2) return 0; /创建流式套接字,基于TCP(SOCK_STREAM) SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0); /Socket地址结构体的创建 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);/转换Unsigned long型为网络字节序格 addrSrv.sin_family = AF_INET;/指定地址簇 addrSrv.sin_port = htons(6000); /指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换 /将套接字绑定到一个端口号和本地地址上 bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR);/必须用sizeof,strlen不行 listen(socSrv, 5); SOCKADDR_IN addrClient;/字义用来接收客户端Socket的结构体 int len = sizeof(SOCKADDR);/初始化参数,这个参数必须进行初始化,sizeof /循环等待接受客户端发送请求 while (1) /等待客户请求到来;当请求到来后,接受连接请求, /返回一个新的对应于此次连接的套接字(accept)。 /此时程序在此发生阻塞 SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len); char sendBuf100; sprintf(sendBuf, Welcome %s to CSU, inet_ntoa(addrClient.sin_addr);/格式化输出 /用返回的套接字和客户端进行通信 send(sockConn, sendBuf, strlen(sendBuf)+1, 0);/多发送一个字节 /接收数据 char recvBuf100; 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的兼容就不是很好,会产生错误提示“no operator defined which takes a right-hand operand of type _int64”。此时使用C的写法:scanf(%I64d,&a)和printf(%I64d,a),就可以正确输入输出了。课设过程中遇到的第二个大难题是生成项0x104C11DB7超出范围,和同学讨论后确定是电脑机器位数不够造成的,可以进行强制转换,经过各种尝试,最终确定强制转换类型为:_int64 POLY=(_int64) 0x254028D1*0x7,其中0x254028D1*0x7=0x104C11DB7。课设中遇到的第三个难题简直是灾难性的,那就是在第一次检查过程中才发现看错了题目条

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论