[英]select(), recv() and EWOULDBLOCK on non-blocking sockets
我想知道以下情況是否真實?!
對於recv()
你會得到EAGAIN
而不是EWOULDBLOCK
,是的,這是可能的。 由於您剛剛使用select()
進行了檢查,因此發生了以下兩種情況之一:
select()
和recv()
之間排出了輸入緩沖區。 這是可能的,但只有在您有多個線程/進程試圖從同一個套接字讀取的情況下。
我知道在流行的桌面操作中出現錯誤,其中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.