C++网络编程快速入门(四):EPOLL模型使用
目錄
- 基本使用方法
- step1:創建epollfd
- step2:將fd綁定到epollfd
- step3:調用epoll_wait檢測事件
- epoll_wait與poll、select區別所在
- 水平觸發與邊緣觸發
基本使用方法
step1:創建epollfd
- 創建一個epollfd,若epoll_create調用成功,則返回一個非負值的epollfd,否則返回-1
step2:將fd綁定到epollfd
有了epollfd之后,我們有三種需求:
1、將需要檢測事件的其他fd綁定到這個epollfd上
2、修改一個已經綁定到epollfd的fd的事件類型
3、在不需要的時候將fd從epollfd上解綁
都需要依托函數epoll_ctl完成:
__epfd:即epollfd
__op:操作類型,有三種EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL。分別對應著在epollfd上添加、修改、移除fd,當為EPOLL_CTL_DEL時,__event參數忽略,置NULL
__fd:需要備操作的fd
__event:一個epoll_event結構體的地址
具體結構如下:
返回值:
調用成功,返回0;
調用失敗,返回-1,通過errno錯誤碼可以獲取具體的錯誤原因。
step3:調用epoll_wait檢測事件
/* Wait for events on an epoll instance "epfd". Returns the number oftriggered events returned in "events" buffer. Or -1 in case oferror with the "errno" variable set to the specific error code. The"events" parameter is a buffer that will contain triggeredevents. The "maxevents" is the maximum number of events to bereturned ( usually size of "events" ). The "timeout" parameterspecifies the maximum wait time in milliseconds (-1 == infinite).This function is a cancellation point and therefore not marked with__THROW. */ extern int epoll_wait (int __epfd, struct epoll_event *__events,int __maxevents, int __timeout);__events:一個epoll_event結構數組的首地址,是一個輸出參數,在函數調用成功后,在events中存放的是與就緒事件相關的epoll_event結構體數組。
__maxevents:數組元素個數
__timeout:超時時間,單位為ms
返回值:調用成功返回有事件的fd數量,若返回0,表示超時。若返回-1,表示調用失敗。
使用示例如下:
epoll_wait與poll、select區別所在
在第二講中演示了select的基本使用方式:C++網絡編程快速入門(二):Linux下使用select演示簡單服務端程序
select和epoll底層機制一樣,所以這里只看select。
可以發現調用完select之后,需要在原來的clientfds數組中遍歷,然后加條件判斷是否是有事件的。
而epoll_wait調用完之后是直接返回一個篩選過后的有事件的events數組。
所以:
在fd數量比較多但是某段時間內的就緒事件fd數量較少時,epoll_wait函數更加高效。
也就是epoll模型更適合用在socket連接數量較大而活躍的連接較少的情景下
水平觸發與邊緣觸發
epoll具有兩種模式:邊緣觸發模式(Edge Trigger,ET)和水平觸發模式(Level Trigger,LT)。
區別在于:
1、LT:一個事件只要有,就會一直觸發
2、ET:一個事件從無到有,才會觸發
以socket讀事件為例:
水平模式下,只要socket上有未讀完的數據,就會一直產生EPOLLIN事件。
邊緣模式下,socket上每新來一次數據就會觸發一次,如果上一次觸發后未將socket上的數據讀完,也不會再觸發,除非再新來一次數據。
以socket寫事件為例:
水平模式下,只要socket上TCP窗口一直不飽和,就會一直觸發EPOLLOUT事件。
邊緣模式下,只有TCP窗口由不飽和變成飽和 或者 再一次變成不飽和,才會觸發EPOLLOUT事件。
這對于編程的啟示是:
1、對于非阻塞socket,如果epoll使用邊緣模式檢測事件可讀,那么一旦觸發,一定要一次性把socket上數據收取干凈,即循環調用recv函數直到recv出錯
2、如果是水平模式,可以根據業務一次性收取固定字節數
下面總結一下兩者在編碼上需要注意的地方:
1、LT模式下,讀事件觸發后可以按需收取想要的字節數,不用把本次數據收取干凈;
ET模式下,讀事件必須把數據收取干凈,因為我們不一定再有機會收取數據了。
2、LT模式下,不需要寫事件時一定要及時移除,避免不必要地觸發且浪費CPU資源。
ET模式下,寫事件觸發后,如果還需要下一次的寫事件觸發來驅動任務(例如發送上次剩余的數據),則我們需要繼續注冊一次檢測可寫事件
3、LT會導致多次觸發,ET優點是觸發次數少
總結
以上是生活随笔為你收集整理的C++网络编程快速入门(四):EPOLL模型使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全网通手机多少钱啊?
- 下一篇: C++智能指针使用指南 part2:智能