在C#中处理字节数组

13

我有一个表示完整TCP/IP数据包的字节数组。为了澄清,该字节数组按照以下顺序排列:

(IP头 - 20个字节)(TCP头 - 20个字节)(有效负载 - X个字节)

我有一个名为Parse的函数,接受一个字节数组并返回一个TCPHeader对象。它看起来像这样:

TCPHeader Parse( byte[] buffer );

给定原始字节数组,这是我目前调用此函数的方法。

byte[] tcpbuffer = new byte[ 20 ];
System.Buffer.BlockCopy( packet, 20, tcpbuffer, 0, 20 );
TCPHeader tcp = Parse( tcpbuffer );

有没有一种方便的方法可以将TCP字节数组即完整的TCP/IP数据包的第20-39个字节传递给Parse函数,而不需要先将其提取到一个新的字节数组中?

在C++中,我可以这样做:

TCPHeader tcp = Parse( &packet[ 20 ] );

在C#中有类似的东西吗?如果可能,我想避免创建和随后垃圾回收临时字节数组。


节省时间和精力,使用现有的网络捕获/解析框架,如SharpPcap或Pcap.Net。编写TCP头解析器就像编写解析HTML的Perl脚本一样。已经有许多不同风格的轮子在野外被发现了。 - Evan Plaice
可能重复: https://dev59.com/NHNA5IYBdhLWcg3wL62x - Jon
11个回答

0

一些回答的人

tcpbuffer.Skip(20).Take(20);

做错了。这是一个优秀的解决方案,但代码应该看起来像:

packet.Skip(20).Take(20);

你应该在主要的“packet”上使用Skip和Take方法,而且你发布的代码中不应该存在“tcpbuffer”。此外,你不必使用“System.Buffer.BlockCopy”。
“JaredPar”几乎正确,但他忘记了Take方法。
TCPHeader tcp = Parse(packet.Skip(20));

但他没有在tcpbuffer上犯错。 你发布的代码的最后一行应该是这样的:

TCPHeader tcp = Parse(packet.Skip(20).Take(20));

但是,如果你想使用System.Buffer.BlockCopy而不是Skip和Take,因为可能在性能上更好,正如Steven Robbins所回答的:“但是System.Buffer.BlockCopy/System.Array.Copy可能更有效率”,或者你的Parse函数无法处理IEnumerable<byte>,或者你更习惯于在你发布的问题中使用System.Buffer.Block,那么我建议简单地将tcpbuffer变量设置为非局部变量,而是私有的受保护的公共的内部的静态的,或者非字段(换句话说,它应该在执行你发布的代码的方法之定义和创建)。这样,tcpbuffer只会被创建一次,并且每当你通过System.Buffer.BlockCopy行传递代码时,它的值(字节)将被设置。

这样,你的代码看起来可以像这样:

class Program
{
    //Your defined fields, properties, methods, constructors, delegates, events and etc.
    private byte[] tcpbuffer = new byte[20];
    Your unposted method title(arguments/parameters...)
    {
    //Your unposted code before your posted code
    //byte[] tcpbuffer = new byte[ 20 ]; No need anymore! this line can be removed.
    System.Buffer.BlockCopy( packet, 20, this.tcpbuffer, 0, 20 );
    TCPHeader tcp = Parse( this.tcpbuffer );
    //Your unposted code after your posted code
    }
    //Your defined fields, properties, methods, constructors, delegates, events and etc.
}

或者仅仅是必要的部分:

private byte[] tcpbuffer = new byte[20];
...
{
...
        //byte[] tcpbuffer = new byte[ 20 ]; No need anymore! This line can be removed.
        System.Buffer.BlockCopy( packet, 20, this.tcpbuffer, 0, 20 );
        TCPHeader tcp = Parse( this.tcpbuffer );
...
}

如果你执行了:

private byte[] tcpbuffer;

如果要这样做,那么您必须在构造函数中添加以下行:

this.tcpbuffer = new byte[20];

或者

tcpbuffer = new byte[20];

你知道在tcpbuffer之前不必输入this.,这是可选的,但如果你将其定义为静态的,那么你就不能这样做。相反,你需要输入类名和点'.',或者直接输入字段名(只需输入字段名即可)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接