常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum_校验和算法-程序员宅基地

技术标签: c语言  音视频  linux  进程 线程 节点 网络通信  

常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum

相关思路和源码来自网络,自己只是整理, 做笔记用。

并未完整完善正确归纳,只是个人理解初步做笔记记录。

在实现业务需求过程中,通常要用到相关一些校验算法,简单整理常用校验算法并做笔记:

常用校验算法简单说明:

1:校验和:按每个字节,计算累加和,

2:异或校验:定义初值,按每个字节异或,求结果。

3:CRC校验:已有很多的标准及计算方式,可以返回8字节,16字节,32字节的结果。

受益匪浅的文章:https://blog.csdn.net/u013073067/article/details/86621770

​ 设置crc值和多项式码;依次遍历每个字节,与crc值进行异或;crc值取出最低位的值,并右移一位;如果最低位值位1,则于多项式码进行异或;循环直到8位结束。

crc查表思想:观察,内部有个循环,每次对一个字节(8位)的循环中,对crc码的数字是不变的,这里与多项式码相关,可以直接用数组代替这里的求值。(crc表与crc返回8/16/32位有关,与多项式码有关)

4:LRC校验:是不可靠的,先求和,再对结果取反+1

5:checksum:对checksum值归0,每16bit求和,不够16bit的高位补0,如果checksum溢出,则高16bit和低16bit相加进行处理(依次循环判断)。

测试demo:

//实现对原数据进行checksum计算校验测试demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
//校验和  返回一个字节
unsigned char Check(const unsigned char *buf, int len)  
{
      
    int iSum = 0; 
    for (int i = 0;i < len;i++)  
    {
      
        iSum += buf[i];  
    }  
    iSum %= 0x100;   //也可以&0xff
    return (unsigned char)iSum;  
} 

//异或校验 返回一个字节
unsigned char CheckXor(const char *strData,int len)  
{
      
    char checksum = 0;  
    for (int i = 0;i < len;i++)  
    {
      
        checksum = checksum ^ strData[i];  
    }  
    return (unsigned char)checksum;  
}  

//电子通信领域非常常用,已经有一些特定的计算方式
//CRC校验 (返回两个字节 高字节在前,低字节在后)  循环冗余校验
unsigned short int CRC(const unsigned char *buf, int leng)  
{
      
    unsigned short int  Reg,temp,Crccode,i,j;  
    Reg = 0xFFFF;  					//设置crc的值    FF FF
    Crccode = 0xA001;     			//定义的一个多项式码,最终都会与这个码异或
    for ( i=0;i<leng;i++ )  
    {
         
        Reg ^= *(buf+i);  			//进行异或  与crc的低8位
        	// ==》注意这里的循环 其实都是固定的值,可以直接计算生成一个表来直接获取
        for ( j=0;j<8;j++ )  
        {
         
            temp=Reg&0x0001;      	//获取当前最低位的数字
            Reg=Reg>>1;  			//向右移一位
            if( temp==0x0001 )   	//判断移出的最低位的值,如果为1,则与上文定义的多项式码进行异或,为0,则不处理
                Reg^=Crccode;   
        }   
    }  								//重复处理完所有的数据
    return (Reg<<8 | Reg>>8);   //(Reg^ 0xffff)   ==>这里其实做了反转
} 

// 纵向冗余校验 异或校验和 不可靠
//LRC校验 求和  取反  +1
unsigned char LRC(const unsigned char *auchMsg, unsigned short usDataLen)  
{
      
    unsigned char uchLRC=0;  
    while(usDataLen--)  
    {
      
        uchLRC+=*auchMsg++;  
    }  
    return ((unsigned char)(-((char)uchLRC)));  
} 


//补码求和
unsigned char Check1(const unsigned char *buf, int len)
{
    
    int iSum = 0;
    for (int i = 0;i < len;i++)
    {
    
      iSum += buf[i];
    }
    iSum = 256 - iSum;
   	return (unsigned char)iSum;
}

//把传入checksum置为0  每2个字节求和
//这里没有加入溢出情况  将高16bit和低16bit相加处理
uint32_t checksum(const void *buf, size_t len, uint32_t sum)
{
    
	/* workaround gcc strict-aliasing warning */
	uintptr_t ptr = (uintptr_t)buf;
	typedef uint16_t __attribute__((__may_alias__)) u16_p;
	const u16_p *u16_buf = (const u16_p *)ptr; //把数据按照2byte进行划分

	//减少循环次数而已
	while (len >= (sizeof(*u16_buf) * 4)) {
     //把2byte对应的值,依次累加到一个4byte值中
		sum += u16_buf[0];
		sum += u16_buf[1];
		sum += u16_buf[2];
		sum += u16_buf[3];
		len -= sizeof(*u16_buf) * 4;
		u16_buf += 4;
	}
	while (len >= sizeof(*u16_buf)) {
    	//把不够4位的,也加入sum中
		sum += *u16_buf;
		len -= sizeof(*u16_buf);
		u16_buf += 1;
	}

	/* if length is in odd bytes */
	if (len == 1)	//如果最后的数据不够2byte,其实就是当成2byte处理,高位补0
		sum += *((const uint8_t *)u16_buf);

	return sum;	//这里对最终的结果是如何处理的? 参考具体代码或者业务
}

int main(int argc, char* argv[])
{
    

	//校验和测试  返回一个字节
	const char * src_data = "abcdefghi";
	printf("check %02x \n", Check((const unsigned char*)src_data, strlen(src_data))); //check 8d 

	printf("CheckXor %02x  \n", CheckXor((const char*)src_data, strlen(src_data)));  //CheckXor 61 

	printf("CRC : %02x   \n", CRC((const unsigned char*)src_data, strlen(src_data)));	//CRC : 7f00 

	printf("LRC: : %02x   \n", LRC((const unsigned char*)src_data, strlen(src_data)));   //LRC: : 73

	printf("Check1: %02x   \n", Check1((const unsigned char*)src_data, strlen(src_data))); //Check1: 73 

	printf("sizeof(char*) = %lu \n", sizeof(char*));
	unsigned int cksum = checksum((const void*)src_data, strlen(src_data), 0); //checksum : 6a06
	cksum = (cksum == 0xffff) ? cksum : (uint16_t)~cksum;
	printf("checksum : %02x  \n", cksum);

//使用简单的异或的方案,进行简单的测试
	const char* data = "2|4|12312|119|{\"InternalFleetNum\":\"12345\",\"CoordX\":1178263,\"CoordY\":2083177,\"Heading\":121.7,\"LocationCode\":\"AVB\",\"RequestId\":1234567}";
	printf("data is [%s] \n",data);
	char* buff = NULL;
	buff = (char*)malloc(strlen(data) +2);
	memset(buff, 0, strlen(data) +2);
	memcpy(buff, data, strlen(data));
	printf("buff is [%s] \n",buff);
	unsigned char check_xor = CheckXor((const char*)data, strlen(data));
	printf("check_xor = [%c] \n", check_xor);
	memcpy(buff+strlen(data), (char*)&check_xor, 1);
	printf("buff adn check_xor is [%s] \n",buff);


	//试一下校验  收到的是buff  然后数据的总长度是 strlen(data)+1 
	unsigned char check_xor1 = CheckXor(buff, strlen(buff)-1);
	printf("check_xor1 is [%c] \n", check_xor1);
	// if(check_xor != (unsigned char)recv_buff+len-1)
	printf("data check_xor is [%c] \n", *(buff+strlen(buff)-1));
	if(check_xor1 == *(buff+strlen(buff)-1))
	{
    
		printf("data is success ! \n");
	}else
	{
    
		printf("data is error! \n");
	}
	return 0;
}


/***************************
check 8d 
CheckXor 61  
CRC : 7f00   
LRC: : 73   
Check1: 73   
sizeof(char*) = 8 
checksum : 6a06  
data is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}] 
buff is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}] 
check_xor = [S] 
buff adn check_xor is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}S] 
check_xor1 is [S] 
data check_xor is [S] 
data is success ! 
****************************/
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yun6853992/article/details/121534733

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法