2010-04-06 44 views
5

假设我们有一个简单的互联网套接字,并且它将发送10兆字节(因为我想忽略内存问题)的随机数据。 应该使用什么性能差异或最佳实践方法来接收数据?最终的输出数据应该用byte []表示。是的,我知道将任意数量的数据写入内存是不好的,如果我正在下载一个大文件,我不会这样做。但为了论证的缘故,让我们忽略它,并假设它只是少量的数据。我也意识到这里的瓶颈可能不是内存管理,而是套接字接收。我只想知道接收数据的最有效方法是什么。从套接字接收数据的C#性能方法?

一些狡猾的方式能想到的是:

  1. 有一个列表和缓冲区,后缓冲区已满,将其添加到列表中,并在年底list.ToArray()来获得byte []

  2. 将缓冲区写入内存流,完成后构造stream.Length的byte []并将其全部读入以获取byte []输出。

有没有更高效/更好的方法来做到这一点?

回答

3

只需写入MemoryStream,然后致电ToArray - 即可为您构建适当大小的字节数组。这实际上就是List<byte>,但是使用MemoryStream会简单得多。

+0

是的,这似乎是最简单但不错的答案,谢谢! – Daniel 2010-04-06 23:23:21

-1

您可以写入内存流,然后使用流式读取器或类似的东西来获取数据。你在做什么数据?我问,因为从内存的角度来看,在接收数据时将传入数据写入文件或数据库表会更高效,而不是将整个内容存储在内存中。

+0

可能将其转换为字符串 – Daniel 2010-04-06 06:13:05

0

什么是您的数据编码?它是纯ASCII还是其他东西,比如UTF-8/Unicode?

如果它是纯ASCII,您可以只分配一个所需大小的StringBuilder()(从响应的ContentLength头部获取大小),并在将数据转换为字符串后继续将数据附加到构建器使用Encoding.ASCII。

如果是Unicode/UTF8,那么你有一个问题 - 你不能在读取的字节上调用Encoding..GetString(buffer,0,bytesRead),因为bytesRead可能不构成该编码中的逻辑字符串片段。对于这种情况,您需要将整个实体主体缓冲到内存(或文件)中,然后读取该文件并使用编码对其进行解码。

+0

它只是ASCII是的,这是一个非常好的主意!为什么其他编码需要全额才能正确转换? – Daniel 2010-04-06 23:24:36

+0

哦,因为如果他们每个字符使用2个字节,那么如果您收到7个字节并尝试转换它,则会出现问题。但是你可以得到0-6,并缓冲1不是吗?有更多的工作,但更少的内存压力 – Daniel 2010-04-07 01:13:14

1

那么,Jon Skeet的回答很好(像往常一样),但没有代码,所以这里是我的解释。 (工作的罚款对我来说)。

using (var mem = new MemoryStream()) 
{ 
    using (var tcp = new TcpClient()) 
    { 
     tcp.Connect(new IPEndPoint(IPAddress.Parse("192.0.0.192"), 8880)); 
     tcp.GetStream().CopyTo(mem); 
    } 
    var bytes = mem.ToArray(); 
} 

(为什么不将二者结合起来using S'好吧,如果你要调试,你可能想释放你的时间在看收到的字节之前TCP连接。)

此代码将接收多个数据包并汇总其数据,FYI。所以这是一个很好的方式来简单地接收连接期间发送的所有tcp数据。