2012-01-03 50 views
9

假設本地linux主機上的TCP套接字與遠程主機處於連接狀態。本地主機使用epoll_wait通知遠程主機套接字上的事件。Epoll和遠程單向關機

如果遠程主機分別叫:

shutdown(s,SHUT_WR); 

其連接端口,以指明它完成發射,什麼事件(S)將epoll_wait本地主機爲它的插座上的回報?

我假設EPOLLIN總是會返回並且隨後的recv調用將返回0以指示遠程端已完成傳輸。

EPOLLHUP或EPOLLRDHUP呢? (這兩個事件有什麼區別)?

甚至EPOLLERR?

如果遠程主機調用「關閉」而不是「關閉」,上述任何一個的答案是否會改變?

回答

18

我在做了繁重的工作以找到答案後自己回答。

監聽epoll事件的套接字通常會在遠程對等方調用關閉或關閉(SHUT_WR)時收到一個EPOLLRDHUP(除了EPOLLIN)事件標誌。這並不意味着套接字已經死亡。隨後對recv()的調用將返回套接字上的任何未讀數據,並最終返回「0」來指示EOF。如果遠程對等端只有一半的關閉端口,甚至可以發回數據。

一個值得注意的例外是,如果遠程對等端正在使用其套接字上啓用的SO_LINGER選項,並且延時值爲「0」。關閉這樣一個套接字的結果可能會導致發送TCP RST而不是FIN。從我讀過的,連接重置事件將產生一個EPOLLHUP或EPOLLERR。 (我沒有時間去確認,但它是有道理的)。

有一些文檔建議有一些不支持EPOLLRDHUP的舊版Linux實現,因爲這樣會生成EPOLLHUP。

在我的特殊情況下,我發現在特殊情況下使用EPOLLHUP或EPOLLRDHUP事件代碼並不太有趣。相反,只要將這些事件與EPOLLIN/EPOLLOUT相同,並根據需要調用recv()(或send())。但要密切關注從recv()和send()返回的返回代碼。

+1

我對這裏的行爲有更多疑問,所以我詳細介紹了這些交互:https://medium.com/where-the-flamingcow-roams/down-the-epoll-rabbit-hole-5c0447cb6329 – flamingcow 2016-02-24 18:56:47