它們都是有用的代碼示例,只是在不同的情況下。讓我們來挑選你的第一個例子中添加一些代碼:
Socket socket = ...;
byte[] buffer = new byte[1024 * 32];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
socket.BeginSend(buffer, 0, bytesRead , SocketFlags.None, null, null);
// Wait for completion doing something else?
}
在這種情況下buffer
被重用每次然後是,數據將被覆蓋,因爲你的時間讀一大塊它的預期的行爲,你用它你繼續。
你的第二個例子是非常不同的:你正在填充一個buffer
讀數據,但你沒有讀所有的數據在一起,你每讀一個較小的塊,然後offset
目標buffer
必須增加。
它們有何不同?在第一種情況下,緩衝區可以儘可能小(理想情況下即使是一個字節),多次讀取也會消耗輸入流。在第二種情況下,緩衝區必須足夠大以容納您需要的所有數據。
// Note we need to know file size in advance and buffer must be big enough
// to accommodate all data we need
int read, offset = 0;
while(count > 0 && (read = source.Read(buffer, offset, count)) > 0) {
socket.BeginSend(buffer, offset , read, SocketFlags.None, null, null);
// Here we don't need to wait BeginSend() completes.
offset += read;
count -= read;
}
哪一個更好?很難說,如果你一次性分配所有內存,那麼你很少需要通過增加offset
來增加offset
(我唯一可以考慮的是性能優化,因爲在輸入流上的塊大小或者當你想要 - 並行 - 在讀取新數據時對接收到的數據進行一些處理)。相比之下分配足夠大到可以容納所有數據的緩衝區至少有兩大弊端:
- 你必須知道文件的大小提前(和它並非總是如此);
- 如果文件足夠大,那麼您將運行內存不足。
一般(IMO)如果第一種方法(重複使用相同的緩衝區)在大多數情況下還不錯,你可能有從單一的讀取(和非阻塞發送)性能增益是大多數網絡可以忽略不計情況和缺點是嚴重的。總結:
1 2
Unknown file size yes no
Can run out of memory yes no
Parallel processing friendly no yes
Performance optimized no yes
當然,你也可以「混」兩種方法:一種大與多個較小的讀取循環緩衝區,每個讀你超前偏移指針開始一個新的並行讀取和做處理在上一個(S)。有了這個,你可以從兩種方法中獲得好處,但調整起來有點棘手(因爲併發訪問和可能重疊的讀/寫)。
我不明白。是第一個樣本覆蓋,第二個樣本增加了偏移量,不覆蓋。你的問題是什麼? – 2014-10-28 09:08:04
@SriramSakthivel如果您通過網絡發送文件並不斷寫入overriting 0索引,那麼接收方已經讀取了位於流開頭的第一個字節的誰? – 2014-10-28 09:09:58
通常發送的消息具有'End Of Text'字符(請參見ascii表格),告訴您消息已完成。第一個通常在內存較少時使用(因爲您已經預先定義了緩衝區的長度,您可能會從第二個例子得到'超出範圍錯誤的索引') – jbutler483 2014-10-28 09:11:58