簡體   English   中英

非阻塞套接字上的select(),recv()和EWOULDBLOCK

[英]select(), recv() and EWOULDBLOCK on non-blocking sockets

我想知道以下情況是否真實?!

  1. 非阻塞TCP套接字上的select()(RD)表示套接字已就緒
  2. 以下recv()將返回EWOULDBLOCK,盡管調用select()

對於recv()你會得到EAGAIN而不是EWOULDBLOCK ,是的,這是可能的。 由於您剛剛使用select()進行了檢查,因此發生了以下兩種情況之一:

  • 其他東西(另一個線程)已經在select()recv()之間排出了輸入緩沖區。
  • 在套接字上設置了接收超時,它在沒有收到數據的情況下過期。

在Linux上,它甚至記錄了這可能發生,正如我讀到的那樣。

看到這個問題:

選擇系統調用的虛假就緒通知

這是可能的,但只有在您有多個線程/進程試圖從同一個套接字讀取的情況下。

我知道在流行的桌面操作中出現錯誤,其中O_NONBLOCK TCP套接字,特別是那些在環回接口上運行的套接字,有時在select()報告套接字准備好讀取之后從recv()返回EAGAIN 在我的情況下,這發生在另一方半關閉發送流之后。

有關更多詳細信息,請參閱我的OCaml網絡應用程序環境分發版的NX庫中的t_nx.ml的源代碼。 鏈接

是的,這是真的。 這是一種可能發生的方式:

未來對TCP協議的修改增加了一方“撤銷”它發送的信息的能力,前提是它還沒有被另一方的應用層接收。 此功能在連接上協商。 另一方向你發送一些數據,你得到一個select命中。 在您調用recv之前,另一方使用此新擴展“撤消”數據。 您的read會出現“阻塞”錯誤,因為沒有可讀取的數據。

select函數是一種狀態報告功能,不具備未來保證。 假設select on命中現在確保后續操作不會阻塞,就像使用任何其他狀態報告功能一樣無效。 它與使用access一樣糟糕,試圖確保后續操作不會因為不正確的權限而失敗,或者使用statfs來確保后續寫入不會因完整磁盤而失敗。

雖然我的應用程序是單線程的,但我注意到所描述的行為在RHEL5中並不罕見。 TCP和UDP套接字都設置為O_NONBLOCK(設置的唯一套接字選項)。 select()報告套接字已准備就緒,但以下recv()返回EAGAIN。

在多線程環境中,兩個線程從套接字讀取是可能的。 這是一個多線程應用程序嗎?

如果你沒有在這個套接字上調用select()和recv()之間的任何其他系統調用,那么recv()將永遠不會返回EAGAIN或EWOULDBLOCK。

我不知道它們對recv-timeout意味着什么,但是,POSIX標准在這里沒有提到它,所以你可以安全地調用recv()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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