epoll 事件中發現
就EPOLLIN , EPOLLOUT , EPOLLPRI可以用.
EPOLLERR 和 EPOLLHUP什麼情況下才能監測出這種問題啊.
我的內核是2.6.20
可是用EPOLLRDHUP的時候編譯包錯.
RecvMessThread.cpp:48: error: ‘EPOLLRDHUP’ was not declared in this scope
2.
1、listen fd,有新連接請求,觸發EPOLLIN。
2、對端發送普通數據,觸發EPOLLIN。
3、帶外數據,只觸發EPOLLPRI。
4、對端正常關閉(程序裡close(),shell下kill或ctr+c),觸發EPOLLIN和EPOLLRDHUP,但是不觸發EPOLLERR和EPOLLHUP。
關於這點,以前一直以為會觸發EPOLLERR或者EPOLLHUP。
再man epoll_ctl看下後兩個事件的說明,這兩個應該是本端(server端)出錯才觸發的。
5、對端異常斷開連接(只測了拔網線),沒觸發任何事件。
附man:
EPOLLIN 連接到達;有數據來臨;
The associated file is available for read(2) operations.
EPOLLOUT 有數據要寫
The associated file is available for write(2) operations.
EPOLLRDHUP 這個好像有些系統檢測不到,可以使用EPOLLIN,read返回0,刪除掉事件,關閉close(fd);
如果有EPOLLRDHUP,檢測它就可以直到是對方關閉;否則就用上面方法。
Stream socket peer closed connection, or shut down writing half
of connection. (This flag is especially useful for writing sim-
ple code to detect peer shutdown when using Edge Triggered moni-
toring.)
EPOLLPRI 外帶數據
There is urgent data available for read(2) operations.
EPOLLERR 只有采取動作時,才能知道是否對方異常。即對方突然斷掉,是不可能
有此事件發生的。只有自己采取動作(當然自己此刻也不知道),read,
write時,出EPOLLERR錯,說明對方已經異常斷開。
EPOLLERR 是服務器這邊出錯(自己出錯當然能檢測到,對方出錯你咋能
直到啊)
Error condition happened on the associated file descriptor.
epoll_wait(2) will always wait for this event; it is not neces-
sary to set it in events.
EPOLLHUP
Hang up happened on the associated file descriptor.
epoll_wait(2) will always wait for this event; it is not neces-
sary to set it in events.
EPOLLET 邊緣觸發模式
Sets the Edge Triggered behavior for the associated file
descriptor. The default behavior for epoll is Level Triggered.
See epoll(7) for more detailed information about Edge and Level
Triggered event distribution architectures.
EPOLLONESHOT (since Linux 2.6.2)
Sets the one-shot behavior for the associated file descriptor.
This means that after an event is pulled out with epoll_wait(2)
the associated file descriptor is internally disabled and no
other events will be reported by the epoll interface. The user
must call epoll_ctl() with EPOLL_CTL_MOD to re-enable the file
descriptor with a new event mask.
關於EPOLLERR:
!!!!!!socket能檢測到對方出錯嗎?目前為止,好像我還不知道如何檢測。
但是,在給已經關閉的socket寫時,會發生EPOLLERR,也就是說,只有在采取行動(比如
讀一個已經關閉的socket,或者寫一個已經關閉的socket)時候,才知道對方是否關閉了。
這個時候,如果對方異常關閉了,則會出現EPOLLERR,出現Error把對方DEL掉,close就可以
了。!!!!!!!
關於EPOLLHUP:
!!!!!!socket能檢測到對方出錯嗎?目前為止,好像我還不知道如何檢測。
但是,在給已經關閉的socket寫時,會發生EPOLLERR,也就是說,只有在采取行動(比如
讀一個已經關閉的socket,或者寫一個已經關閉的socket)時候,才知道對方是否關閉了。
這個時候,如果對方異常關閉了,則會出現EPOLLERR,出現Error把對方DEL掉,close就可以
了。!!!!!!!
3.各類事件
1)監聽的fd,此fd的設置等待事件:
EPOLLIN ;或者EPOLLET |EPOLLIN
由於此socket只監聽有無連接,談不上寫和其他操作。
故只有這兩類。(默認是LT模式,即EPOLLLT |EPOLLIN)。
說明:如果在這個socket上也設置EPOLLOUT等,也不會出錯,
只是這個socket不會收到這樣的消息。
2)客戶端正常關閉
client 端close()聯接
server 會報某個sockfd可讀,即epollin來臨。
然後recv一下 , 如果返回0再掉用epoll_ctl 中的EPOLL_CTL_DEL , 同時close(sockfd)。
有些系統會收到一個EPOLLRDHUP,當然檢測這個是最好不過了。只可惜是有些系統,
上面的方法最保險;如果能加上對EPOLLRDHUP的處理那就是萬能的了。
3)客戶端異常關閉:
客戶端異常關閉,並不會通知服務器(如果會通知,以前的socket當然會有與此相關
的api)。正常關閉時read到0後,異常斷開時檢測不到的。服務器再給一個已經關閉
的socket寫數據時,會出錯,這時候,服務器才明白對方可能已經異常斷開了(讀也
可以)。
Epoll中就是向已經斷開的socket寫或者讀,會發生EPollErr,即表明已經斷開。
4)EpollIn:
5)監聽的skocket只需要EpollIn就足夠了,EpollErr和EpollHup會自動加上。
監聽的socket又不會寫,一個EpollIn足矣。
4. 補充 EpollErr
當客戶端的機器在發送“請求”前,就崩潰了(或者網絡斷掉了),則服務器一端是無從知曉的。
按照你現在的這個“請求響應方式”,無論是否使用epoll,都必須要做超時檢查。
因此,這個問題與epoll無關。
因此,EpollErr這種錯誤必須是有動作才能檢測出來。
服務器不可能經常的向客戶端寫一個東西,依照有沒有EpollErr來判斷
客戶端是不是死了。
因此,服務器中的超時檢查是很重要的。這也是以前服務器中作死後確認的原因。
新的代碼裡也是時間循環,時間循環....
!!!服務器中的超時檢查!!!很重要