[英]Why doesn't recv block until it receives all of the data?
為什么在收到所有數據之前, recv
系統只調用阻塞? 每次我看到一個recv
調用時,都會在while循環中繼續調用recv
直到所有數據都存在。 為什么不首先讓recv
阻止?
您可以使用MSG_WAITALL
標志在收到所有數據之前請求recv塊。 但是,如果信號到達,則執行某些工作(即接收部分數據)的系統調用無法自動重新啟動以接收其余信號。 因此,即使使用MSG_WAITALL
,也可能會在緩沖區已滿之前返回recv調用,並且您必須准備好處理這些情況。 鑒於此,許多人只是選擇循環,而不是使用鮮為人知的標志,如MSG_WAITALL
。
至於為什么默認情況是這樣的,有幾個原因可以想到:
telnet
協議,它在設計BSD套接字API時很流行。 你通常會在同一時間內接收的字節屈指可數,沒有長度字段告訴你多少數據的期望,而且你需要顯示的數據的時候了 。 在此處填充緩沖區之前阻塞是沒有意義的。 與使用SMTP或IMAP等面向行的協議一樣,在收到所有命令之前,您不知道命令的持續時間。 recv
通常用於數據報套接字,它接收單個數據報,即使它比提供的緩沖區小得多。 流式套接字的自然擴展是盡可能多地返回,而無需等待。 但最重要的,因為你需要做好准備, 無論如何處理部分緩沖,這是很好的,迫使人們在默認情況下處理它,所以他們轉起來的錯誤在他們的循環早期-而不是讓他們仍然隱藏,直到信號到了一個不幸的時刻。
在大多數情況下,您不知道有多少數據是“所有數據”。 例如,如果您在面向行的協議中接收數據,則一行可能是10個字節長或65個字節長。
您可以將套接字標志更改為阻止或非阻止。 您的具體案例實際上與阻止或不阻止無關。
默認情況下使網絡功能以您描述的方式運行是沒有意義的 - 如果流永遠不會結束......如果程序永遠不會結束? Prima facia,這似乎不是健康的默認行為。
閱讀http://www.scottklement.com/rpg/socktut/nonblocking.html以熟悉阻塞和非阻塞IO。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.