2010-04-06 45 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數據。