c# - 在 C# 中验证模块化和校验和

标签 c# ascii checksum

我正在使用一个嵌入式系统,该系统返回包含(我认为是)modular sum checksum 的 ASCII 数据。 .我想验证这个校验和,但根据制造商的规范我一直无法这样做。我也无法根据描述完成相反的操作并计算出相同的校验和。

设备的每个响应都采用以下格式:

╔═════╦═══════════════╦════════════╦════╦══════════╦═════╗
║ SOH ║ Function Code ║ Data Field ║ && ║ Checksum ║ ETX ║
╚═════╩═══════════════╩════════════╩════╩══════════╩═════╝

例子:

SOHi11A0014092414220&&FBEA

其中 SOH 是 ASCII 1。例如

#define SOH "\x01"

校验和说明如下:

The Checksum is a series of four ASCII-hexadecimal characters which provide a check on the integrity of all the characters preceding it, including the control characters. The four characters represent a 16-bit binary count which is the 2's complemented sum of the 8-bit binary representation of the message characters after the parity bit (if enabled) has been cleared. Overflows are ignored. The data integrity check can be done by converting the four checksum characters to the 16-bit binary number and adding the 8-bit binary representation of the message characters to it. The binary result should be zero.

我尝试了对规范的几种不同解释,包括忽略 SOH 和符号,甚至忽略函数代码。 在这一点上,我对规范的解释或我一直用来测试的代码中肯定遗漏了一些非常明显的东西。下面是一个简单的示例(数据取自实时系统),如果它是正确的,则验证变量中较低的单词将为 0:

static void Main(string[] args)
{
    unchecked
    {
        var data = String.Format("{0}{1}", (char) 1, @"i11A0014092414220&&");
        const string checkSum = "FBEA";

        // Checksum is 16 bit word
        var checkSumValue = Convert.ToUInt16(checkSum, 16);

        // Sum of message chars preceeding checksum
        var mySum = data.TakeWhile(c => c != '&').Aggregate(0, (current, c) => current + c);
        var validate = checkSumValue + mySum;

        Console.WriteLine("Data: {0}", data);
        Console.WriteLine("Checksum: {0:X4}", checkSumValue);
        Console.WriteLine("Sum of chars: {0:X4}", mySum);
        Console.WriteLine("Validation: {0}", Convert.ToString(validate, 2));
        Console.ReadKey();
    }
}

编辑

虽然@tinstaafl 提供的解决方案适用于这个特定示例,但在提供更大的记录时不起作用,如下所示:

SOHi20100140924165011000007460904004608B40045361000427DDD6300000000427C3C66000000002200000745B4100045B3D8004508C00042754B900000000042774D8D0000000033000007453240004531E000459F5000420EA4E100000000427B14BB000000005500000744E0200044DF4000454AE000421318A0000000004288A998000000006600000744E8C00044E7200045469000421753E600000000428B4DA50000000&&

BA6C

理论上,您可以不断递增/递减字符串中的值,直到校验和匹配为止,碰巧使用字符 1 而不是 ASCII SOH 控制字符给出了正确的值,在这种情况下是巧合。

最佳答案

不确定这是否正是您要查找的内容,但是通过对 SOH 使用整数 1 而不是 char 值 1,计算所有字符的总和并转换 validate 变量为 16 位整数,我能够得到等于 0 的验证:

var data = (@"1i11A0014092414220&&");
const string checkSum = "FBEA";

// Checksum is 16 bit word
var checkSumValue = Convert.ToUInt16(checkSum, 16);

// Sum of message chars preceeding checksum
var mySum = data.Sum<char>(c => c);
var validate = (UInt16)( checkSumValue + mySum);

Console.WriteLine("Data: {0}", data);
Console.WriteLine("Checksum: {0:X4}", checkSumValue);
Console.WriteLine("Sum of chars: {0:X4}", mySum);

Console.WriteLine("Validation: {0}", Convert.ToString(validate, 2));
Console.ReadKey();

关于c# - 在 C# 中验证模块化和校验和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26025219/

相关文章:

c# - 如何将 StreamReader 转换为字符串?

c# - 我们如何定义字符串常量而不是数组

c# - 获取字符串中所有字符的数值

python - 将 ascii 查找表存储在 Python 文件中

c - 字符串序列分析器

c# - 复制包含所有文件和文件夹的目录

c# - 在 WCF 中不使用 CallBack 将数据推送到客户端

algorithm - Luhn算法为什么要乘以2?

ruby - 为在线商店生成订单号的最佳方式?

java - 适合在 Postgres 9 和 Java 中唯一标识一系列数字的校验和