tcp中的crc检验算法原理_在数据传输过程中的CRC 算法的简单说明

4debd5e478abf8ce2f75df52c00e8afe.png

CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式。在嵌入式软件开发中,经常要用到CRC 算法对各种数据进行校验。因此,掌握基本的CRC算法应是嵌入式程序员的基本技能。可是,我认识的嵌入式程序员中能真正掌握CRC算法的人却很少,平常在项目中见到的CRC的代码多数都是那种效率非常低下的实现方式。

从奇偶校验说起

所谓通讯过程的校验是指在通讯数据后加上一些附加信息,通过这些附加信息来判断接收到的数据是否和发送出的数据相同。比如说RS232串行通讯可以设置奇偶校验位,所谓奇偶校验就是在发送的每一个字节后都加上一位,使得每个字节中1的个数为奇数个或偶数个。比如我们要发送的字节是0x1a,二进制表示为0001 1010。

采用奇校验,则在数据后补上个0,数据变为0001 1010 0,数据中1的个数为奇数个(3个)

采用偶校验,则在数据后补上个1,数据变为0001 1010 1,数据中1的个数为偶数个(4个)

接收方通过计算数据中1个数是否满足奇偶性来确定数据是否有错。

奇偶校验的缺点也很明显,首先,它对错误的检测概率大约只有50%。也就是只有一半的错误它能够检测出来。另外,每传输一个字节都要附加一位校验位,对传输效率的影响很大。因此,在高速数据通讯中很少采用奇偶校验。奇偶校验优点也很明显,它很简单,因此可以用硬件来实现,这样可以减少软件的负担。因此,奇偶校验也被广泛的应用着。

奇偶校验就先介绍到这来,之所以从奇偶校验说起,是因为这种校验方式最简单,而且后面将会知道奇偶校验其实就是CRC 校验的一种(CRC-1)。

累加和校验

另一种常见的校验方式是累加和校验。所谓累加和校验实现方式有很多种,最常用的一种是在一次通讯数据包的最后加入一个字节的校验数据。这个字节内容为前面数据包中全部数据的忽略进位的按字节累加和。比如下面的例子:

我们要传输的信息为: 6、23、4

加上校验和后的数据包:6、23、4、33

这里 33 为前三个字节的校验和。接收方收到全部数据后对前三个数据进行同样的累加计算,如果累加和与最后一个字节相同的话就认为传输的数据没有错误。

累加和校验由于实现起来非常简单,也被广泛的采用。但是这种校验方式的检错能力也比较一般,对于单字节的校验和大概有1/256 的概率将原本是错误的通讯数据误判为正确数据。之所以这里介绍这种校验,是因为CRC校验在传输数据的形式上与累加和校验是相同的,都可以表示为:通讯数据 校验字节(也可能是多个字节)

初识 CRC 算法

CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数除以另一个数。得到的余数作为校验数据附加到原数据后面。还以上面例子中的数据为例:

6、23、4 可以看做一个2进制数: 0000011000010111 00000010

假如被除数选9,二进制表示为:1001

则除法运算可以表示为:

9b308a98fb6110f1647f9fc4e8818467.png

可以看到,最后的余数为1。如果我们将这个余数作为校验和的话,传输的数据则是:6、23、4、1

CRC 算法和这个过程有点类似,不过采用的不是上面例子中的通常的这种除法。在CRC算法中,将二进制数据流作为多项式的系数,然后进行的是多项式的乘除法。还是举个例子吧。

比如说我们有两个二进制数,分别为:1101 和1011。

1101 与如下的多项式相联系:1x3+1x2+0x1+1x0=x3+x2+x0

1011与如下的多项式相联系:1x3+0x2+1x1+1x0=x3+x1+x0

两个多项式的乘法:(x3+x2+x0)(x3+x1+x0)=x6+x5+x4+x3+x3+x3+x2+x1+x0

得到结果后,合并同类项时采用模2运算。也就是说乘除法采用正常的多项式乘除法,而加减法都采用模2运算。所谓模2运算就是结果除以2后取余数。比如3 mod 2 = 1。因此,上面最终得到的多项式为:x6+x5+x4+x3+x2+x1+x0,对应的二进制数:111111

加减法采用模2运算后其实就成了一种运算了,就是我们通常所说的异或运算:

0+0=0

0+1=1

1+0=1

1+1=0

0-0=0

1-0=1

0-1=1

1-1=0

上面说了半天多项式,其实就算是不引入多项式乘除法的概念也可以说明这些运算的特殊之处。只不过几乎所有讲解 CRC 算法的文献中都会提到多项式,因此这里也简单的写了一点基本的概念。不过总用这种多项式表示也很罗嗦,下面的讲解中将尽量采用更简洁的写法。

除法运算与上面给出的乘法概念类似,还是遇到加减的地方都用异或运算来代替。下面是一个例子:

要传输的数据为:1101011011

除数设为:10011

在计算前先将原始数据后面填上4个0:11010110110000,之所以要补0,后面再做解释。

0c2a57c614fd45ff2dc43e48e9993056.png

从这个例子可以看出,采用了模2的加减法后,不需要考虑借位的问题,所以除法变简单了。最后得到的余数就是CRC 校验字。为了进行CRC运算,也就是这种特殊的除法运算,必须要指定个被除数,在CRC算法中,这个被除数有一个专有名称叫做“生成多项式”。生成多项式的选取是个很有难度的问题,如果选的不好,那么检出错误的概率就会低很多。好在这个问题已经被专家们研究了很长一段时间了,对于我们这些使用者来说,只要把现成的成果拿来用就行了。

最常用的几种生成多项式如下:

CRC8=X8+X5+X4+X0

CRC-CCITT=X16+X12+X5+X0

CRC16=X16+X15+X2+X0

CRC12=X12+X11+X3+X2+X0

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0

有一点要特别注意,文献中提到的生成多项式经常会说到多项式的位宽(Width,简记为W),这个位宽不是多项式对应的二进制数的位数,而是位数减1。比如CRC8中用到的位宽为8的生成多项式,其实对应得二进制数有九位:100110001。另外一点,多项式表示和二进制表示都很繁琐,交流起来不方便,因此,文献中多用16进制简写法来表示,因为生成多项式的最高位肯定为1,最高位的位置由位宽可知,故在简记式中,将最高的1统一去掉了,如CRC32的生成多项式简记为04C11DB7实际上表示的是104C11DB7。当然,这样简记除了方便外,在编程计算时也有它的用处。

对于上面的例子,位宽为4(W=4),按照CRC算法的要求,计算前要在原始数据后填上W个0,也就是4个0。

位宽W=1的生成多项式(CRC1)有两种,分别是X1和X1+X0,读者可以自己证明10 对应的就是奇偶校验中的奇校验,而11对应则是偶校验。因此,写到这里我们知道了奇偶校验其实就是CRC校验的一种特例,这也是我要以奇偶校验作为开篇介绍的原因了。

CRC算法的编程实现

说了这么多总算到了核心部分了。从前面的介绍我们知道CRC校验核心就是实现无借位的除法运算。下面还是通过一个例子来说明如何实现CRC校验。

假设我们的生成多项式为:100110001(简记为0x31),也就是CRC-8

则计算步骤如下:

(1) 将CRC寄存器(8-bits,比生成多项式少1bit)赋初值0

(2) 在待传输信息流后面加入8个0

(3) While (数据未处理完)

(4) Begin

(5) If (CRC寄存器首位是1)

(6) reg = reg XOR 0x31

(7) CRC寄存器左移一位,读入一个新的数据于CRC寄存器的0 bit的位置。

(8) End

(9) CRC寄存器就是我们所要求的余数。

实际上,真正的CRC 计算通常与上面描述的还有些出入。这是因为这种最基本的CRC除法有个很明显的缺陷,就是数据流的开头添加一些0并不影响最后校验字的结果。这个问题很让人恼火啊,因此真正应用的CRC 算法基本都在原始的CRC算法的基础上做了些小的改动。

所谓的改动,也就是增加了两个概念,第一个是“余数初始值”,第二个是“结果异或值”。

所谓的“余数初始值”就是在计算CRC值的开始,给CRC寄存器一个初始值。“结果异或值”是在其余计算完成后将CRC寄存器的值在与这个值进行一下异或操作作为最后的校验值。

096cbc13e7dd45a3d9a0f7cba8ec575a.png

加入这些变形后,常见的算法描述形式就成了这个样子了:

(1) 设置CRC寄存器,并给其赋值为“余数初始值”。

(2) 将数据的第一个8-bit字符与CRC寄存器进行异或,并把结果存入CRC寄存器。

(3) CRC寄存器向右移一位,MSB补零,移出并检查LSB。

(4) 如果LSB为0,重复第三步;若LSB为1,CRC寄存器与0x31相异或。

(5) 重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。

(6) 重复第2至第5步直到所有数据全部处理完成。

(7) 最终CRC寄存器的内容与“结果异或值”进行或非操作后即为CRC值。

而网上的代码.h.c文件很多,可以试一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

和氟西汀类似的备注_撒狗粮:可爱又霸气的给男朋友的微信备注

在微信里,你的男朋友是怎么被你备注的? 是“老公”,“儿子”,还是“死鬼”? 看看各地网友们的精彩备注吧!——————————————————————小垃圾大宝贝小闹闹周少爷chou狗软蛋蛋小可爱免费鸭…

ogg 查看某条更新_明道云Web 6.1更新:日历视图上线

更新时间:2020年12月22日(周二)19点预计时长:2小时是否停服:否版本代号:Web 6.1(移动端需同步强制更新)主要更新功能日历视图日历视图让用户能从时间维度排列并管理业务数据&#xf…

服务器的可维护性,可靠性和可维护性

可靠性和可维护性可靠性一直是戴尔服务器产品线的一大亮点,R515也不例外。如内部结构所示,当你打开R515机箱的时候,你可以很明显地看到风扇的数量、分布的各个组件和双电源机箱。你也可以感觉出从中取出各个组件和拆装机箱都十分简便。配合低…

服务器缺少storportSYS文件,Windows操作系统蓝屏日志分析方法

或许你可以先检测下机器硬件健康状况,详情点击查看检测教程工具:X64 Debuggers And Tools-x64_en-us 下载地址:链接:http://pan.baidu.com/s/1cAO2ey 密码:9oms源文件:DMP蓝屏日志 ,文件目录查看…

合并工具_你值得拥有这个PDF合并工具 免费获取转换方法

合并PDF文件?很多人在日常生活中经常会需要使用到合并文档的要求,但是不是所有的人都能够很熟练的去合并我们生活中常用的文件,例如PDF,例如Word和Excel等等,其实只要我们学会了PDF合并的方法,以上文件的合…

事物与持久化_跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现...

提到MySQL的事物,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关。而事务的ACID(即原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)可以说涵盖了事务…

cookie里面用到的关键字_晓龙吊打面试官系列:synchronized关键字入门(同步方法与同步代码块)...

文章目录一、 线程安全问题二、synchronized简介1) 原子性2) 可见性3) 有序性4)可重入1. 什么是synchronized2.什么是同步3.synchronized的特性4.synchronized的实现原理(了解即可)三、synchronized的用法1. 同步方法2. 同步代码块四、对象锁和类锁1)对象锁2)类锁1.对象锁的探索…

mysql 函数返回查询结果_MySQL数据库中常用查询函数简介

MYSQL中的常用函数count(*)---相当于统计表的行数,在统计结果的时候,不会忽略列值为NULL的记录。 select count(*) from yinxiong;Count(列名)表示统计此列当中总行数(不计算null所在的行)Count(distinct 列名&#xf…

属性值动态调整_这可能是你见过最牛的CAD粗糙度动态块了!

好课推荐:零基础CAD:点我CAD家装:点我 周站长CAD:点我CAD机械:点我revit教程:点我CAD建筑:点我CAD三维:点我全屋定制:点我 ps教程:点我苹果版CAD:点我 3dmax教…

bootstrap mysql源码_Django+Bootstrap+Mysql 搭建个人博客 (六)

6.1.comments插件(1)安装pip install django-contrib-comments(02)settingsINSTALLED_APPS [django.contrib.sites,django_comments,]SITE_ID 1(3)website/urlurl(r^comments/, include(django_comments.urls)),(4)修改源码django_comments/abstracts.py第36行原代码site mode…

mysql 查看索引 命令_MySQL命令篇之库、表、索引、用户、视图及SELECT查询

大纲一、库管理二、表管理三、索引管理四、用户管理五、视图管理六、SELECT查询一、库管理(1)、创建数据库CREATE DATABASE db_name [CHARACTER SET [] charset_name] [COLLATE [] collation_name];mysql> CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET gbk COLLATE …

mysql 数据修改记录日志_mysql对数据的更新操作记录在哪个日志中?

mysql对数据的更新操作记录在通用查询日志和二进制日志中。通用查询日志用来记录用户的所有操作,包括启动和关闭 MySQL 服务、更新语句和查询语句等;二进制日志会以二进制的形式记录数据库的各种操作,但不记录查询语句。(推荐教程&#xff1a…

mysql insert 二进制_MYSQL 插入二进制数的 2 种方法。

方法 1、insert into TableName set column ;方法 2、insert into TableName .... values(.....);------------------------------------------------------------------------------------------------------------------------------------------create table T(x bit(8));方…

mysql怎么分组查询所有数据库_Mysql-4 分组查询与子查询

1、查询结果的分组操作a、分组允许把数据分为多个组,以便能对每个组进行聚集计算b、分组是在select语句的group by 子句中建立的注意:group by 只是创建分组,但并不保证分组里面的数据的排列顺序,需要使用order by 子句对分组里面…

mysql update upper_MySQL数据处理函数upper、abs、date

1. 数据处理函数文本处理函数upper()转换大写函数SQL> select vend_name, upper(vend_name) as vend_name_upcase from vendors order by vend_name;soundex()发音类似函数SQL> select cust_name, cust_contact from customers where cust_contact Y. Lie;SQL> selec…

java 获取类方法_Java之反射机制三:获取类的方法

一.实体类BigDog.javapackage reflex;public class BigDog extends Dog {private Integer age;public String name;public BigDog(){}private void getDog(){}private BigDog(Integer age, String name) {this.age age;this.name name;}public String getName() {return name…

java语言50到100之间素数和_用JAVA语言编写一程序,求100以内的所有素数

满意答案fdewj5902017.02.13采纳率&#xff1a;40% 等级&#xff1a;9已帮助&#xff1a;316人12345678910111213141516171819public static void main(String[] args) { for (int i 2; i < 100; i) { int temp (int) Math.sqrt(i); …

java矩阵面积_Java基础 矩阵面积

提供 数据结构与算法题目 的平台是LintCode&#xff0c;参考链接是&#xff1a;http://www.lintcode.com/zh-cn/问题描述&#xff1a;参考代码&#xff1a;public class Rectangle {/** Define two public attributes width and height of type int.*/// write your code herep…

java判断线程是否wait_Java并发编程之线程间通讯(上)wait/notify机制

线程间通信如果一个线程从头到尾执行完也不和别的线程打交道的话&#xff0c;那就不会有各种安全性问题了。但是协作越来越成为社会发展的大势&#xff0c;一个大任务拆成若干个小任务之后&#xff0c;各个小任务之间可能也需要相互协作最终才能执行完整个大任务。所以各个线程…

python土味情话_Python 将土味情话语录设置为桌面壁纸

本文编写于 128 天前&#xff0c;最后修改于 128 天前&#xff0c;其中某些信息可能已经过时。41041-3yfokd0irbe.png38220-tlrmwji3zwo.pngimport osimport tempfileimport timeimport requestsimport win32apiimport win32conimport win32guifrom PIL import Image, ImageDra…