C#,是否可以在没有副本的情况下将字节*转换为字节[]?什么是最快的方式?

时间:2011-07-27 18:58:17

标签: c# arrays sockets pointers unsafe

我有一个来自套接字连接的大字节[] receiveBuffer,其中包含多个数据包。

我想将单个数据包传递到应用程序中的下一层,但我不想将每个数据包复制到新数组中。

我现在正在做这样的事情

fixed (byte* rxBufferPtr = receiveBuffer)
{
    while(more_packets_in_rx_buf)
    {
       NewPacketReceived(rxBufferPtr + offset, packetSize);
        // NewPacketReceived params: NewPacketReceived(byte* packet, int size)
       offset += packetSize;
    }
}

我想传递托管数组而不是指针和大小,新的NewPacketReceived参数将是:NewPacketReceived(byte [] packet)

我永远不会重复使用接收缓冲区,在它已满后会创建一个新缓冲区。

2 个答案:

答案 0 :(得分:3)

不,你不能没有复制。通过偏移或长度是要走的路。你不应该不安全,它并不总是更快。 ArraySegment结构可以帮助您将偏移量与数组一起传递。

答案 1 :(得分:1)

“byte *仍然是托管内存”?我不明白这个说法。 byte *是指向未知大小的字节数组的指针。相反,托管字节数组具有已知大小。托管字节数组不是内存指针(只要有指针,当指针变为无效时,数据就无法“管理”到另一个内存位置)。根据定义,不是指向未知大小的数组的指针?

请注意,Marshal.Copy性能很差(您应该能够找到样本测试程序,将Marshal.Copy的性能与使用插入收藏搜索引擎名称搜索的其他技术进行比较)。通常使用自己的迭代和赋值来获得更好的复制性能。通过64位(8字节)的块进行分配,因为CPU可以比逐字节复制更快地完成。当字节数组没有填充到8个字节时,最后几个字节将逐字节复制。

再次,AFAIK,没有副本就没有办法从byte *转换为byte [],因此专注于尽可能快地制作不可避免的副本。或者,您可以寻求避免转换的方法。例如,仅在byte []中工作或仅在byte *中工作。 System.Net.Sockets.Socket类在byte []中工作 - 如果你正在使用那个类,你可以坚持使用你的应用程序的byte []吗?