在C#中计算Internet(即IP,即RFC791)校验和

有趣的是,我可以在除C#之外的几乎所有语言中找到Internet Checksum的实现。 有没有人有实现分享?

请记住, 互联网协议规定:

“校验和字段是报头中所有16位字的一个补码和的16位补码。为了计算校验和,校验和字段的值为零。”

可以从Math博士那里找到更多解释。

有一些效率指针可供使用,但这对我来说并不是一个很大的问题。

请包括你的测试! (编辑:关于测试其他人的代码的有效评论 – 但是我要离开协议并且没有我自己的测试向量,而是宁愿对其进行unit testing,而不是投入生产以查看它是否与当前使用的相匹配! 😉

编辑:这是我提出的一些unit testing。 他们测试一个遍历整个字节集的扩展方法。 如果您在测试中发现错误,请发表评论。

[TestMethod()] public void InternetChecksum_SimplestValidValue_ShouldMatch() { IEnumerable value = new byte[1]; // should work for any-length array of zeros ushort expected = 0xFFFF; ushort actual = value.InternetChecksum(); Assert.AreEqual(expected, actual); } [TestMethod()] public void InternetChecksum_ValidSingleByteExtreme_ShouldMatch() { IEnumerable value = new byte[]{0xFF}; ushort expected = 0xFF; ushort actual = value.InternetChecksum(); Assert.AreEqual(expected, actual); } [TestMethod()] public void InternetChecksum_ValidMultiByteExtrema_ShouldMatch() { IEnumerable value = new byte[] { 0x00, 0xFF }; ushort expected = 0xFF00; ushort actual = value.InternetChecksum(); Assert.AreEqual(expected, actual); } 

我知道我把这个存放在某个地方…… http://cyb3rspy.wordpress.com/2008/03/27/ip-header-checksum-function-in-c/

好吧,我从旧的代码库中挖出了一个实现,它通过了我在问题中指定的测试,所以这里(作为扩展方法):

 public static ushort InternetChecksum(this IEnumerable value) { byte[] buffer = value.ToArray(); int length = buffer.Length; int i = 0; UInt32 sum = 0; UInt32 data = 0; while (length > 1) { data = 0; data = (UInt32)( ((UInt32)(buffer[i]) << 8) | ((UInt32)(buffer[i + 1]) & 0xFF) ); sum += data; if ((sum & 0xFFFF0000) > 0) { sum = sum & 0xFFFF; sum += 1; } i += 2; length -= 2; } if (length > 0) { sum += (UInt32)(buffer[i] << 8); //sum += (UInt32)(buffer[i]); if ((sum & 0xFFFF0000) > 0) { sum = sum & 0xFFFF; sum += 1; } } sum = ~sum; sum = sum & 0xFFFF; return (UInt16)sum; }