2017-01-16 77 views
0

我的應用程序類似於libevent,使用epoll(在級別觸發模式下)來檢測I/O活動並調用回調來處理它。當epoll發出信號時,recv()調用會如何阻止?

我最近發現,我的TCP/IP套接字被阻塞,這是一個意外,但我仍然不希望recv()調用阻止FD被epoll報告爲有讀取活動掛起。即使插座出現錯誤,當然recv()會返回並告訴我。

我對此有什麼誤解?
在這種情況下,什麼樣的網絡狀況可能導致recv()阻塞?

+0

您是否已將'MSG_WAITALL'傳遞給'recv()'?在這種情況下,即使某些(但不是全部)字節可能已經可用,該功能可能會阻止。 –

+0

@RalphTandetzky:編號''recv(fd,buf,BUFSIZE,0);' –

+2

通常會發生這種情況,因爲epoll + recv不是原子的,所以如果epoll和recv之間發生其他事情,套接字可能不再準備好在你打電話給recv的時候閱讀。但是,如果沒有[MVCE](http://stackoverflow.com/help/mcve),就不可能說出你的情況可能會發生什麼。 –

回答

1

在Linux select手冊頁:

在Linux下,選擇()可能會報告套接字文件描述符爲「準備 閱讀」,而不過隨後的讀取塊。這個 可能例如發生在數據已經到達但是在檢查時 具有錯誤的校驗和並被丟棄。可能有其他 情況,其中文件描述符虛假地報告爲 就緒。因此,在應該不會阻塞的套接字上使用O_NONBLOCK可能更安全。

(是的,我知道的epoll()是不一樣的選擇(),但我懷疑相同的基礎條件適用於)

我認爲,如果你真的想避免阻塞,唯一安全的方法是將你的套接字設置爲非阻塞模式。

+0

啊哈 - 這可能是。謝謝:) –

0

如果您使用Epoll來輪詢EPOLLIN事件,那麼之後的recv調用應立即返回。此外,我希望你正在使用非阻塞套接字。如果你想查找錯誤,那麼你可以查找EPOLLERR事件。如果套接字在epoll信號後關閉,則recv應該失敗。 epoll_wait,epoll_ctl和套接字創建的代碼片段將有助於調試問題。