【epoll問題】EPOLLRDHUP使用導致無法接受資料

_Zero_Lee發表於2018-09-05

EPOLLRDHUP

問題:

客戶端關閉連結時

原來的操作是程式碼層操作,即 觸發EPOLLIN,recv返回0,關閉套接字即可。

現在,使用EPOLLRDHUP狀態,當客戶端傳送資料後立馬關閉,(呼叫close(sockfd)),伺服器無法接受資料,直接關閉。

程式碼如下:

if(events[i].events & EPOLLRDHUP
	|| events[i].events & EPOLLHUP
	|| events[i].events & EPOLLERR)
{
    epoll(epollFd, EPOLL_CTL_DEL, clientFd, NULL);
    close(clientFd);
}

對程式碼進行修改:

if( !(events[i].events & EPOLLIN)
    &&( events[i].events & EPOLLRDHUP
	    || events[i].events & EPOLLHUP
	    || events[i].events & EPOLLERR))
{
    epoll(epollFd, EPOLL_CTL_DEL, clientFd, NULL);
    close(clientFd);
}

會導致一直recv返回0,還是無法接受資料。 

參考該篇博文:https://blog.csdn.net/c1520006273/article/details/50439019

結論:

EPOLLIN = 0x0001

EPOLLRDHUP = 0x2000

對端連線斷開觸發的epoll事件會包含EPOLLIN | EPOLLRDHUP,即0x2001

採用以下三種方法,實驗都失敗了

1)在接收到EPOLLRDHUP 訊號時,應該先recv,然後再關閉   

   -> 觸發EPOLLRDHUP的訊號,列印出來是0x2001,然後觸發EPOLLIN,但是recv會返回0,並沒有先接收資料(recv >0),然後再recv = 0

2)或者在傳送客戶端設定SO_LINGER選項,等緩衝區資料傳輸完畢後關閉

    -> 並不能帶來sleep的效果(客戶端sleep(5)可以實現伺服器端正常接收)

3)調換錯誤檢測和輸入檢測的順序,即先檢測是否EPOLLIN,然後檢測EPOLLRDHUP

     -> recv < 0 

 

同一個世界 同一個問題

https://stackoverflow.com/questions/27175281/epollrdhup-not-reliable

相關文章