.NET Socket和NetworkStream都提供了Read方法,當沒有可用的數據時,該方法將阻塞。問題是,如果客戶端不知道消息的大小,沒有可靠的方式來理解服務器何時完成發送消息。知道何時停止從HTTP套接字上讀取
我的問題是 - 高級別的庫(如HTTP級WebRequest)使用什麼原理來停止從套接字讀取並向客戶端呈現完整消息,而不訴諸任何類型的讀取超時?看起來HTTP協議不提供任何「EOF」令牌......
.NET Socket和NetworkStream都提供了Read方法,當沒有可用的數據時,該方法將阻塞。問題是,如果客戶端不知道消息的大小,沒有可靠的方式來理解服務器何時完成發送消息。知道何時停止從HTTP套接字上讀取
我的問題是 - 高級別的庫(如HTTP級WebRequest)使用什麼原理來停止從套接字讀取並向客戶端呈現完整消息,而不訴諸任何類型的讀取超時?看起來HTTP協議不提供任何「EOF」令牌......
HTTP 1.1通過使用兩種機制之一來管理它。在標頭中發送content-length,或者使用chunked transfer encoding。分塊傳輸器編碼是HTTP 1.1 over HTTP 1.0的最大優點之一,在沒有發送內容長度的情況下,不能可靠地檢測到傳輸結束,導致傳輸問題與有效負載的實際結束之間的不確定性。在某些情況下(例如通過HTTP的音頻流),沒有可能指示傳輸結束的內容長度或其他編碼,但在這種情況下,它對客戶端來說並不重要。
在HTTP中,content-length
HTTP頭定義了何時可以關閉套接字。
在TCP中,這是任意的,通常客戶端或服務器發送特殊消息來通知該連接正在終止。
有一些方法可以檢查套接字是否有數據掛起。一個是簡單地檢查每個套接字的Pending
屬性,並且只有在有數據時才調用Receive。但是,這並不能很好地擴展,我只會建議在單個連接等應用中使用它。
Socket.Select函數可以使用套接字的IList,並在短時間後,將該列表減少爲僅包含具有待處理數據的套接字。然後您可以安全地呼叫接收而不會阻塞。
另一種方法是首選,它使用異步套接字API。 (在NetworkStream上調用BeginReceive
或BeginRead
)。在這些情況下,呼叫不會被阻止,您可以在呼叫後繼續執行代碼。當數據在套接字上掛起時,您將傳遞一個函數作爲參數。這是在.NET線程池中的後臺線程中處理的,因此這裏涉及併發問題,與前兩種方法不同。通過使用中斷告訴CPU何時數據在網絡上等待,而不是像Select一樣反覆輪詢數據,異步事件在OS中的低層完成。
'Socket.Select'不在Windows中使用'select'調用? :(也就是說,除非它是一個非常愚蠢的實現,它不應該「反覆輪詢」(它不會在其他語言/庫中這麼做) – 2011-02-24 19:51:59
我不知道select是如何實現的,但我的意思是是,用戶需要保持輪詢與選擇的呼叫,而在異步方法,他們不需要輪詢,但只會在數據未決時被中斷。 –
如果選擇[快速]輪詢 - 想法是*等待*在句柄變爲可用於讀/寫/ oob(並且呼叫將阻塞直到這種時間或如果[可選]超時發生或以其他方式中斷)。我同意'開始/結束'的建議。 – 2011-02-24 20:23:04
非常感謝,正是我需要的! – Konstantin