Posted on 2010-11-20 23:07
S.l.e!ep.¢% 閱讀(771)
評論(0) 編輯 收藏 引用 所屬分類:
epoll
我原先的client端代碼流程如下:??
創建一個socket
設為異步socket(fcntl)
將socket加入epoll
connect到遠端(此時connect調用返回非0,但errno為EINPROGRESS,表示正在建立連接中)
epoll_wait之
捕獲到EPOLLOUT事件,此時便認為connect已經成功,client端開始發消息
這個過程通常能夠運轉,但是線上環境復雜多變,如果發生這種情況:server進程調用listen開始偵聽后,被gdb或信號掛住了,此時異步connect會怎樣?很遺憾,client端的epoll_wait依然返回EPOLLOUT,甚至往此socket里發消息都返回成功,只有當發的消息多得占完了server端的tcp緩沖以后(窗口收縮到很小),send調用才開始失敗。這時候用 losf -i 看網絡連接也很有趣,client端的機器顯示連接建立了,server端的卻顯示沒有這個連接。
仔細想想,OS這樣做是正確的,畢竟connect的語義只是“連接”,當server掛住時,連接還是能成功的,但你能不能往里面發消息那就是另外一回事了。
所以對于應用來說,異步socket想要知道connect后連接是不是可以正常收發數據了,還是要靠應用層的一問一答才能知道。
====== 2010.5.14 ======
昨天同事朱照遠給了一個更正確的解決方案,可參考之:
“收到EPOLLOUT也不能認為是TCP層次上connect(2)已經成功,要調用getsockopt看SOL_SOCKET的SO_ERROR是否為0。若為0,才表明真正的TCP層次上connect成功。至于應用層次的server是否收/發數據,那是另一回事了。”