我有一个字节数组,代表一个完整的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#中有类似的东西吗?我想尽可能避免临时字节数组的创建和后续垃圾收集.
您可以在.NET框架中看到并且我建议在此处使用的常见做法是指定偏移量和长度.因此,使您的Parse函数也接受传递的数组中的偏移量,以及要使用的元素数.
当然,同样的规则也适用于传递类似C++的指针 - 不应修改数组,否则如果您不确定何时将使用数据,则可能导致未定义的行为.但是,如果您不再修改数组,这没有问题.
ArraySegment
在这种情况下我会通过.
您可以将Parse
方法更改为:
// Changed TCPHeader to TcpHeader to adhere to public naming conventions. TcpHeader Parse(ArraySegmentbuffer)
然后你会改变对此的调用:
// Create the array segment. ArraySegmentseg = new ArraySegment (packet, 20, 20); // Call parse. TcpHeader header = Parse(seg);
使用ArraySegment
不会复制数组,它将在构造函数中为您进行边界检查(这样就不会指定不正确的边界).然后你改变你的Parse
方法来使用段中指定的边界,你应该没问题.
您甚至可以创建一个方便的重载,它将接受完整的字节数组:
// Accepts full array. TcpHeader Parse(byte[] buffer) { // Call the overload. return Parse(new ArraySegment(buffer)); } // Changed TCPHeader to TcpHeader to adhere to public naming conventions. TcpHeader Parse(ArraySegment buffer)