linux C累加和校验和CRC循环冗余校验的实验报告

linux C累加和校验和CRC循环冗余校验的实验报告

摘要
在计算机中,当数据由发送方传至接收方时,需要进行数据校验。数据校验是为了保证数据的完整性而进行的一种验证操作。通常用一种指定的算法对原始数据计算出一个校验值,接收方用同样的算法也计算出一个校验值,如果接收方计算的校验值正确,则说明数据是完整的。
本实验探讨累加和校验和crc循环冗余校验的原理及在Linux C系统下的实现代码。
累加和校验的原理为在一次通讯数据包的最后加入一个字节的校验数据。这个字节的内容为前面数据包中全部数据进行1的补码和运算,得到的累加和再取反后的值。累加和校验由于实现起来非常简单而被广泛的采用,但是这种校验方式的检错能力比较一般。
crc循环冗余校验的原理为在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码也叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。 校验码的具体生成过程为:假设要发送的信息用多项式C(X)表示,将C(x)左移R位(可表示成C(x)*2R),这样C(x)的右边就会空出R位,这就是校验码的位置。用 C(x)*2R 除以生成多项式G(x)得到的余数就是校验码。
关键字:数据校验、累加和校验、CRC循环冗余校验、Linux
一.总体概括
1.1累加和校验
本实验的累加和校验程序首先读取操作者输入的数据,然后相加计算校验和,再输入相同或不同的数据,以模拟接收方接收到的数据,用同样的方法计算校验和,最后进行数据正确与否的判断并输出结论。
图1累加和总体流程图
图1 累加和总体流程图
1.2crc循环冗余校验
本实验的CRC循环冗余校验程序已给K位信息码和生成多项式,二者做除运算(异或)即得R位的校验码。
CRC总体流程图
图2 crc总体流程图
二.设计思路
2.1算法分析
2.1.1.累加和校验
发送方:1.将发送的进行校验和运算的数据分成若干个8位的位串,每个位串看成一个二进制数。
2.将IP、UDP或TCP的PDU首部中的校验和字段置为0,该字段也参与校验和运算。
3.对这些8位的二进制数进行1的补码和运算,累加的结果再取反码即生成了校验码。将校验码放入校验和字段中。其中1的补码和运算,即带循环进位的加法,最高位有进位时应循环到最低位。
接收方:1.接收方将接收的数据(包括检验和字段)按发送方的同样的方法进行1的补码和运算,累加的结果再取反码。
2.校验,如果上步的结果为0,表示传输正确;否则,说明传输有差错。
2.1.2.crc循环冗余校验
1.将X的最高次幂为R的生成多项式G(X)转换成对应的R+1位二进制数。
2.将信息码左移R位,相当于对应的信息多项式C(X)*2R。
3.用生成多项式(二进制数)对信息码做除,得到R位的余数(注意:这里的二进制做除法得到的余数其实是模2除法得到的余数,并不等于其对应十进制数做除法得到的余数。)。
4.将余数拼到信息码左移后空出的位置,得到完整的CRC码。
2.2程序流程图
2.2.1累加和校验
累加和校验程序流程图
图3 累加和校验程序流程图
2.2.2CRC循环冗余校验
CRC程序流程图
图4 CRC程序流程图

三.实验步骤
3.1累加和校验
1.利用vim文本编辑器新建一个wage1.c文件,打开文件,点击a,i,进入编辑模式,输入代码,点击Esc按钮进入一般模式,输入“:”,进入命令行模式,编写程序后输入“wq”,存盘退出。命令如下:
vim wage.c
2.程序编辑
(1)初始化,定义变量
a[100]:发送方发送的数据 b[100]:接收方接收的数据 cumsum_s=0:发送方计算出的累加和并初始化为0 cumsum_r=0:接收方计算出的累加和并初始化为0 checksum_r:接收方计算出的校验和 checksum_s:发送方计算出的校验和
(2)将算法编写为代码。
3.使用gcc将源代码编译成可执行文件,命令如下:
gcc wage1.c –o wage1.out
4.运行可执行文件,观察运行结果并记录。命令如下:
./wage1.out
5.新建m文件,命令如下:
touch m.txt
6.将运行结果保存到txt文件中,命令如下:
./wage.out > m.txt
如图5、6所示:
在这里插入图片描述
图5 累加和校验Ubuntu命令
在这里插入图片描述
图6 累加和校验运行结果
3.2crc校验
步骤同上文累加和校验,具体命令如图所示:
在这里插入图片描述
图7 CRC校验ubuntu命令
在这里插入图片描述
图8 crc校验结果文件保存
在这里插入图片描述
图9 crc校验文件
在这里插入图片描述
图10 crc校验运行结果
四.待解决的问题
1.本实验中累加和校验的算法中发送方接收的数据需要人工模拟输入,进而进行数据正确性的判断,缺乏逻辑性,省略了数据在发送方和接收方之间的传递过程。
2.CRC循环冗余校验程序提前定义好传输数据和生成多项式,有很大的局限性,结果只是输出校验码,数据传输过程和数据正确性的判断省略。后续可以设计用户任意输入的数据进行CRC校验。
五.实验总结
通过这次实验,我了解了Linux环境下进行C语言编程的基本方法,感受到了ubuntu系统的简便和快捷。Linux系统本身已经良好的集成了进行C语言的基本环境,所以只需在终端输入几个简单的命令,程序即可编译并运行了。
在编写LinuxC程序的过程中,最主要的是方法和思路,每一个C程序的编写都必须提前在脑中捋好思路,想好方法,才可以顺畅的进行;其次是耐心和仔细,如分号的使用、大小写的区分、括号的匹配、语句的拼写、for循环的判断等必须认真。
本实验中用到了基本的vim文本编辑器、gcc编译命令、执行命令./wage.out、新建文件命令touch,执行结果保存成文本文件命令,对各种命令的记忆于我而言还是一个不小的难关,这就要求我必须经常进行练习。
六.附录
6.1累加和校验

#include<stdio.h>
int main()
{ 
 int a[100],b[100];
 int i,cumsum_s=0,cumsum_r=0,checksum_r,checksum_s,n;
 //发送方 
 scanf("%d",&n);//将传送的数据划分为n段 
 for (i=0;i<n;i++){
	scanf("%x",&a[i]);//输入n个数据段 
    cumsum_s+=a[i];//将每个数相加
    if(cumsum_s>0xff){//超过8位,放到低位相加(+1) ,得累加和 
        cumsum_s=(cumsum_s>>16)+(cumsum_s&0xff);                  
        }}
    checksum_s=~cumsum_s; 
    checksum_s=checksum_s&0xff;//得校验和 
 printf("cumsum_s:0x%x\n",cumsum_s);//输出累加和 
 printf("checksum:0x%x\n",checksum_s);//输出校验和 
 //接收方 
 for (i=0;i<n;i++){
	scanf("%x",&b[i]);//输入传送过来的数据,和发送方发送的数据相同(数据正确)和不同 (数据错误) 
     cumsum_r+=b[i];//将每个数相加
     if(cumsum_r>0xff){
        cumsum_r=(cumsum_r>>16)+(cumsum_r&0xff);                  
        }}
    cumsum_r=cumsum_r+checksum_s;//数据相加后再加上发送方传来的校验和 
	if(cumsum_r>0xff){
        cumsum_r=(cumsum_r>>16)+(cumsum_r&0xff);  
	}
	checksum_r=~cumsum_r; 
    checksum_r=checksum_r&0xff; 
    if(checksum_r==0) 
	printf("数据正确"); 
	else
		printf("数据错误");
}

6.2CRC循环冗余校验

#include<stdio.h>
unsigned char POLY=0X13;  //生成项 0x13=10011
unsigned short data=0x035B;  //待测数据 0x035B=11 0101 1011
unsigned short regi=0x0000;  //寄存器 初始化值为0x0000

void GetCrc();

int main()
{
    printf("data=%x\n",data);
    data=data<<4;  //在data后面追加4个0
    GetCrc();
    return 0;
}

void GetCrc()
{
    for ( int cur_bit = 15; cur_bit >= 0; -- cur_bit )   //处理16次,前4次实际上只是加载数据 
    { 
        printf("cur_bit=%d\n",cur_bit);
        if ( (  ( regi >> 4 )  & 0x0001 ) == 0x1 )  //如果最高位是1的话 ,寄存器与 10011异或
            {
                regi = regi ^ POLY; 
                printf("regi^POLY=%x\n",regi);
            }   

        regi <<= 1;  //寄存器左移一位,低位空零
        printf("regi<<1=%x\n",regi);
        unsigned short tmp = ( data >> cur_bit ) & 0x0001;  //加载待测数据1比特到tmp中,tmp只有1比特 
        printf("tmp=%x\n",tmp);
        regi |= tmp;    //这1比特加载到寄存器中 
        printf("regi=%x\n",regi);
        printf("\n\n");
    } 


    if ( ( ( regi >> 4 ) & 0x0001 ) == 0x1 )   regi = regi ^ POLY;    //做最后一次XOR 
   //这时, regi中的值就是CRC 
    printf("%x\n",regi);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值