epoll實現服務器

1、epoll

epoll按照man手冊的說法:是爲處理大批量句柄而作了改進的poll。被公認爲Linux2.6下性能最好的多路I/O就緒通知方法。

epoll有三個相關的系統調用

1)epoll_create

創建一個epoll的句柄。當創建好epoll句柄後,它就是會佔用一個fd值,在linux下如果查看/proc/進程id/fd/,是能夠看到這個fd的,所以在使用完epoll後,必須調用close()關閉,否則可能導致fd被耗盡。

wKioL1ebYbfA2wLvAAAwvnLkJ7w123.png-wh_50

2)epoll_ctl

epoll的事件註冊函數,它不同於select()是在監聽事件時告訴內核要監聽什麼類型的事件,而是在這裏先註冊要監聽的事件類型。

wKiom1ebYu7SIa1lAAAqFSLj4Vw691.png-wh_50

第一個參數是epoll_create()的返回值。

第二個參數表示動作,用三個宏來表示:

wKiom1ebY2OhQYdVAABOsYb8uJ4222.png-wh_50

EPOLL_CTL_ADD:註冊新的fd到epfd中;

EPOLL_CTL_MOD:修改已經註冊的fd的監聽事件;

EPOLL_CTL_DEL:從epfd中刪除一個fd;

第三個參數是需要監聽的fd。

第四個參數是告訴內核需要監聽什麼事。

struct epoll_event的結構:

wKioL1ebY_nwSxAqAAAswkAA7pI385.png-wh_50

events可以是以下幾個宏的集合:

EPOLLIN :表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);

EPOLLOUT:表示對應的文件描述符可以寫;

EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這裏應該表示有帶外數據到來);

EPOLLERR:表示對應的文件描述符發生錯誤;

EPOLLHUP:表示對應的文件描述符被掛斷;

EPOLLET: 將EPOLL設爲邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(LevelTriggered)來說的。

EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列裏。

3)epoll_wait

wKioL1ebZHPi_uAZAABbfjIh9LM527.png-wh_50

收集在epoll監控的事件中已經發送的事件。參數events是分配好的epoll_event結構體數組,epoll將會把發生的事件賦值到events數組中(events不可以是空指針,內核只負責把數據複製到這個events數組中,不會去幫助我們在用戶態中分配內存)。maxevents告之內核這個events有多大,這個 maxevents的值不能大於創建epoll_create()時的size,參數timeout是超時時間(毫秒,0會立即返回,-1將不確定,也有說法說是永久阻塞)。如果函數調用成功,返回對應I/O上已準備好的文件描述符數目,如返回0表示已超時。


2、epoll的兩種工作方式

1)水平觸發(LT)

2)邊緣觸發(ET)

注意:epoll工作在ET模式的時候,必須使用非阻塞套接口,以避免由於一個文件句柄的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。

wKiom1ebZamTO-mJAAAiZJ0FG_I265.png-wh_50

用該函數將套接字設置成非阻塞


3、代碼實現

wKiom1ebZijgikrKAADCsND1FX0942.png-wh_50

wKiom1ebZinSqEiHAACv62oJjRI467.png-wh_50

wKioL1ebZimBrDNTAAC0yd2MxXM816.png-wh_50

wKioL1ebZiqRaX2JAADx-HlyKlo230.png-wh_50

wKiom1ebZivTufgdAADA9fdcm5k339.png-wh_50


使用瀏覽器測試,結果如下:

wKiom1ebZoGy0KSDAAFfTywFdvw972.png-wh_50


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章