2013-03-20 56 views
8

初學者問題再次提問:不久前提問的問題。Socket.Receive何時返回數據?

我想了解這個同步套接字教程http://msdn.microsoft.com/en-us/library/6y0e13d3.aspx,特別是下面代碼中的一行。

問題: 我想確保我瞭解程序流程的正確性。 沒有handler.Receive(bytes)返回?它是否返回並存儲在int bytesRec **中收到的字節數,當它「溢出」且已收到超過1024字節? **如果是這樣的,這可能聽起來很愚蠢,如果更多的字節到達,會發生什麼情況,因爲它將1024字節存儲在* 數據 *變量中,並且不會偵聽當時可能到達的更多字節?或者我不應該擔心它,讓.net處理這個問題?

Socket handler = listener.Accept(); 
data = null; 

// An incoming connection needs to be processed. 
while (true) { 
    bytes = new byte[1024]; 
    int bytesRec = handler.Receive(bytes); 
    // My question is WHEN does the following line 
    // get to be executed 
    data += Encoding.ASCII.GetString(bytes,0,bytesRec); 
    if (data.IndexOf("<EOF>") > -1) { 
     break; 
    } 
} 

回答

10

什麼時候handler.Receive(字節)返回?

文檔:

如果沒有可用的數據用於讀取,該接收方法將阻塞 直到數據是可用的,除非超時值是使用 Socket.ReceiveTimeout設置。如果超時超時值,Receive 調用將拋出SocketException。如果處於非阻塞模式, 並且在協議堆棧緩衝區 中沒有可用數據,則Receive方法將立即完成並拋出一個 SocketException。您可以使用可用屬性來確定是否有 數據可供閱讀。當「可用」不爲零時,請重試 接收操作。


它返回並存儲在INT bytesRec收到時「溢出」,並已收到超過1024個字節的字節數?

不,它總是返回已讀取的字節數。如果沒有,你怎麼能知道bytes哪部分包含有意義的數據以及它的哪部分未被使用?

這是非常重要瞭解插座通常是如何工作的:字節可以在分組抵達,但就接收器而言每個字節應獨立考慮。這意味着,不能保證你會得到發件人發送給他們的塊中的字節,當然也不能保證有足夠的數據來填充緩衝區。

如果您只想以1024字節的塊處理傳入數據,則自己有責任始終調用Receive,直至總共釋放1024字節爲止。

如果是這樣的話,這可能聽起來很傻,會發生什麼,如果有更多的 字節到達,因爲它是存儲在變量中的1024個字節, 不聽那些可能在那個時候抵達多個字節?

讓我們重申Receive將不會在緩衝區中存儲1024個字節,因爲這是緩衝區的大小。它將存儲高達 1024字節。

如果網絡堆棧內部緩衝的數據量超過緩衝區的容量,則會返回1024字節,其餘的將保留在網絡堆棧的緩衝區中,直到您再次撥打Receive。如果Receive已開始將數據複製到緩衝區,並且此時從網絡接收到更多數據,那麼最有可能發生的情況是這些將不得不等待下一個Receive呼叫。

畢竟,在任何時候,有沒有人提供了保證Receive會給你所有數據它可以(儘管當然,這是可取的,它是最會發生什麼的時候)。

+0

您可以認爲接收很像從文件讀取。如果文件中仍有足夠的數據字節(在本例中爲網絡堆棧),它將返回到您的緩衝區大小,否則它將返回其餘數據(可能小於緩衝區大小) 。 – shellster 2013-03-20 13:02:09

+0

@shellster:那種。但是這個描述掩蓋了一個非常重要的事實,即網絡堆棧可能會決定將數據交給它*選擇的任何塊。沒有保證。 – Jon 2013-03-20 13:04:31

+1

@Jon謝謝你的出色答案。當你說「網絡堆棧可能決定將數據以你選擇的任何塊傳遞給你」是否意味着我的客戶端可能會發送「抱歉親愛的,我不是單身但已婚」但我的服務器可能會收到「但已婚」之前「對不起親愛的」?上面的微軟代碼沒有這樣的錯誤檢查... wouldnt tcp/ip照顧,所以我收到正確的順序數據 – 2013-03-20 13:16:00