2

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

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

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

更多解释可以从Dr. Math找到。

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

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

编辑:这是我提出的一些单元测试。他们测试了一个迭代整个字节集合的扩展方法。如果您在测试中发现错误,请发表评论。

[TestMethod()]
public void InternetChecksum_SimplestValidValue_ShouldMatch()
{
    IEnumerable<byte> 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<byte> value = new byte[]{0xFF};
    ushort expected = 0xFF;

    ushort actual = value.InternetChecksum();

    Assert.AreEqual(expected, actual);
}

[TestMethod()]
public void InternetChecksum_ValidMultiByteExtrema_ShouldMatch()
{
    IEnumerable<byte> value = new byte[] { 0x00, 0xFF };
    ushort expected = 0xFF00;

    ushort actual = value.InternetChecksum();

    Assert.AreEqual(expected, actual);
}
4

2 回答 2

4

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

于 2010-02-02T22:07:42.097 回答
1

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

public static ushort InternetChecksum(this IEnumerable<byte> 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;
}
于 2010-02-04T16:00:04.923 回答