簡體   English   中英

為什么在收到所有數據之前不會阻止recv?

[英]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

至於為什么默認情況是這樣的,有幾個原因可以想到:

  • 您經常希望接收部分讀取。 例如,如果您正在逐步顯示數據,或者您將數據代理到其他地方,或者如果數據太大,則無法立即將整個數據緩沖在內存中。 畢竟,如果您只是立即寫入文件,您是否關心將它分成200個寫入而不是150個?
  • 有時您甚至不知道一開始就需要多少數據。 考慮一下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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM