计算在C#中的因特网(又名IP,又名RFC791)校验 [英] Calculate an Internet (aka IP, aka RFC791) checksum in C#

查看:244
本文介绍了计算在C#中的因特网(又名IP,又名RFC791)校验的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有趣的是,我可以找到在互联网校验的实现,除了C#几乎每一种语言。有没有人有共享的实现?



记住,的 internet协议规定:



校验字段是所有16位的一个人的
的补充和的16位的补话在首部。对于
的目的计算校验,校验和字段的值是零。



更多的解释,可以从博士。数学



有一些的效率指针使用,但是这不是一个真正的大关心我在这一点上。



请提供您的测试! (编辑:有关测试别人的代码有效的注释 - 但我将离开协议,并没有我自己的测试向量,而宁愿单元测试比投入生产,以看它是否符合当前正在使用的! ; - )



编辑:这里是我想出了一些单元测试。他们测试它通过整个字节集合迭代的扩展方法。如果你发现在测试中故障请评论。

  [TestMethod的()] 
公共无效InternetChecksum_SimplestValidValue_ShouldMatch()
{
IEnumerable的<位>值=新的字节[1]; //应适用于预期= 0xFFFF的零
USHORT的任何长度的数组;

USHORT实际= value.InternetChecksum();

Assert.AreEqual(预期,实际值);
}

[TestMethod的()]
公共无效InternetChecksum_ValidSingleByteExtreme_ShouldMatch()
{
IEnumerable的<位>值=新的字节[] {}为0xFF;
USHORT预期= 0xFF的;

USHORT实际= value.InternetChecksum();

Assert.AreEqual(预期,实际值);
}

[TestMethod的()]
公共无效InternetChecksum_ValidMultiByteExtrema_ShouldMatch()
{
IEnumerable的<位>值=新的字节[] {为0x00,0xFF的};
USHORT预期=为0xFF00;

USHORT实际= value.InternetChecksum();

Assert.AreEqual(预期,实际值);
}


解决方案

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

 公共静态USHORT InternetChecksum(这IEnumerable的<位>价值)
{
字节[]缓冲= value.ToArray();
INT长度= buffer.Length;
INT I = 0;
UInt32的总和= 0;
UInt32的数据= 0;
,而(长度大于1)
{
数据= 0;
数据=(UInt32的)(
((UInt32的)(缓冲[I])LT;< 8)
|
((UInt32的)(缓冲[I + 1] )及为0xFF)
);

总和+ =数据;
如果((总和&放大器; 0xFFFF0000地址)大于0)
{
总和=总和&放大器; 0xFFFF的;
之和+ = 1;
}

I + = 2;
长度 - = 2;
}

如果(长度大于0)
{
总和+ =(UInt32的)(缓冲液[1] - ;&下; 8);
//总和+ =(UInt32的)(缓冲[I]);
如果((总和&放大器; 0xFFFF0000地址)大于0)
{
总和=总和&放大器; 0xFFFF的;
之和+ = 1;
}
}
和=〜总和;
总和= SUM和放大器; 0xFFFF的;
回报(UINT16)总和;
}


Interestingly, I can find implementations for the Internet Checksum in almost every language except C#. Does anyone have an implementation to share?

Remember, the internet protocol specifies that:

"The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header. For purposes of computing the checksum, the value of the checksum field is zero."

More explanation can be found from Dr. Math.

There are some efficiency pointers available, but that's not really a large concern for me at this point.

Please include your tests! (Edit: Valid comment regarding testing someone else's code - but I am going off of the protocol and don't have test vectors of my own and would rather unit test it than put into production to see if it matches what is currently being used! ;-)

Edit: Here are some unit tests that I came up with. They test an extension method which iterates through the entire byte collection. Please comment if you find fault in the tests.

[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);
}

解决方案

Well, I dug up an implementation from an old code base and it passes the tests I specified in the question, so here it is (as an extension method):

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;
}

这篇关于计算在C#中的因特网(又名IP,又名RFC791)校验的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆