2

興味深いことに、C# を除くほぼすべての言語でインターネット チェックサムの実装を見つけることができます。誰かが共有する実装を持っていますか?

インターネット プロトコルでは、次のことが指定されていることに注意してください。

「チェックサム フィールドは、ヘッダー内のすべての 16 ビット ワードの 1 の補数の合計の 16 ビットの 1 の補数です。チェックサムを計算する目的で、チェックサム フィールドの値はゼロです。」

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 に答える