终于有人把校验说明白了
大家好!我是付工。
我们做上位机开发的时候,经常会听到【校验】这个词。
今天给大家分享关于【校验】的一些个人理解。
校验目的
首先我们思考一下,为什么会存在校验?

我们都知道,计算机底层都是通过二进制的方式进行传输。
但是在实际传输过程中,比特流由于会受到各种干扰,可能会出现比特差错,这种我们称之为误码。误码会导致数据错误,错误的数据带来的影响是巨大的,因此通信务必要保证报文的正确性。
此外,如果报文没有传输完成,但是接收方认为传输完成了,会导致收到的报文是不完整的。针对以上两种情况,我们提出了【校验】这种方式。
校验的目的是为了保证报文的正确性和完整性。
校验一般会有两种形式,一种是底层的校验,比如串口的奇偶校验、以太网的校验和,另一种是应用层的校验,比如CRC校验、异或校验等。
底层校验
1、串口的奇偶校验
串口通信中,奇偶校验通过添加一位校验位来检测数据传输中的错误,确保1的个数为奇数或偶数。 奇偶校验是一种简单而常用的方法,它通过添加一位校验位来确保传输数据中1的个数为奇数或偶数。


2、以太网校验和
待检验报文从头开始,每16位进行一次加法计算,如果遇到进位,则将高于16字节的进位部分的值加到最低位上,这样最终计算出来的和进行一次反码运算,就是检验和。
举例说明:假设数据部分为0xBB 0x5E 0xFC 0xED,对其求校验和。
1、0xBB5E+0xFCED=0x1 B84B;
2、将1放到最低位,得到结果是0xB84C;
3、再进行反码,结果就是0x47B3。
应用层校验
很多情况,单靠底层校验并不能完全保证数据准确性,所以我们还会通过应用层报文校验进行二次校验。
常用的应用层校验有CRC校验、LRC校验、异或校验、累加和校验等。
以累加和校验为例,下面是累加和校验的说明:

其实无论什么校验方式,它的本质就是一种算法。
对于上位机开发来说,就是两个方法,一个是计算校验的方法,代码如下:
/// <summary>
/// 计算8位累加和校验(原始算法)
/// </summary>
public static byte CalculateSumCheck(byte[] data)
{
if (data == null || data.Length == 0)
throw new ArgumentException("输入数据不能为空");
unchecked // 允许算术溢出
{
byte sum = 0;
foreach (byte b in data) sum += b;
return sum;
}
}
另一个是反校验的方法,代码如下:
/// <summary>
/// 验证数据包校验和是否有效
/// </summary>
public static bool ValidatePacket(byte[] packet)
{
if (packet == null || packet.Length < 2)
throw new ArgumentException("数据包长度至少需要2字节");
byte[] payload = packet[..^1]; // 取除最后字节外的所有数据
byte expectedChecksum = CalculateSumCheck(payload);
return packet[^1] == expectedChecksum;
}