C++網絡編程快速入門(四):EPOLL模型使用

目錄

  • 基本使用方法
    • step1:創建epollfd
    • step2:將fd綁定到epollfd
    • step3:調用epoll_wait檢測事件
    • epoll_wait與poll、select區別所在
  • 水平觸發與邊緣觸發

基本使用方法

step1:創建epollfd

  • 創建一個epollfd,若epoll_create調用成功,則返回一個非負值的epollfd,否則返回-1
/* Creates an epoll instance.  Returns an fd for the new instance.The "size" parameter is a hint specifying the number of filedescriptors to be associated with the new instance.  The fdreturned by epoll_create() should be closed with close().  */
extern int epoll_create (int __size) __THROW;

step2:將fd綁定到epollfd

有了epollfd之后,我們有三種需求:
1、將需要檢測事件的其他fd綁定到這個epollfd上
2、修改一個已經綁定到epollfd的fd的事件類型
3、在不需要的時候將fd從epollfd上解綁
都需要依托函數epoll_ctl完成:

/* Manipulate an epoll instance "epfd". Returns 0 in case of success,-1 in case of error ( the "errno" variable will contain thespecific error code ) The "op" parameter is one of the EPOLL_CTL_*constants defined above. The "fd" parameter is the target of theoperation. The "event" parameter describes which events the calleris interested in and any associated user data.  */
extern int epoll_ctl (int __epfd, int __op, int __fd,struct epoll_event *__event) __THROW;

__epfd:即epollfd
__op:操作類型,有三種EPOLL_CTL_ADDEPOLL_CTL_MODEPOLL_CTL_DEL。分別對應著在epollfd上添加、修改、移除fd,當為EPOLL_CTL_DEL時,__event參數忽略,置NULL
__fd:需要備操作的fd
__event:一個epoll_event結構體的地址
具體結構如下:

// 在64位操作系統下,大小為8 byte
typedef union epoll_data
{void *ptr;int fd;uint32_t u32;uint64_t u64;
} epoll_data_t;struct epoll_event
{uint32_t events;	/* 需要檢測的fd事件標志 */epoll_data_t data;	/* 用戶自定義的數據*/
} __EPOLL_PACKED;

返回值
調用成功,返回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,表示調用失敗。
使用示例如下:

    while (true) {epoll_event epollEvents[1024];int n = epoll_wait(epollfd, epollEvents, 1024, 1000);if (n < 0) {if (errno == EINTR) {// 被信號中斷 重試continue;} else {// 出錯 退出break;}} else if (n == 0) {// 超時,繼續重試continue;} else {// 處理事件for (size_t i = 0; i < n; i++) {if (epollEvents[i].events & EPOLLIN) {// 處理可讀事件} else if (epollEvents[i].events & EPOLLOUT) {// 處理可寫事件} else if (epollEvents[i].events & EPOLLERR) {// 處理出錯事件}}}}

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出錯

bool recvEtMode() 
{// 每次只收取256個字節char buf[256];while (true) {int nRecv = ::recv(clientfd, buf, 256, 0);if (nRecv == -1) {if (errno == EWOULDBLOCK) {return true;} else if (errno == EINTR) {continue;} else {return false;}}else if (nRecv == 0) {// 對端關閉了socketreturn false;} else {inputBuffer.add(buf, (size_t)nRecv);}}return true;
}

2、如果是水平模式,可以根據業務一次性收取固定字節數
下面總結一下兩者在編碼上需要注意的地方:
1、LT模式下,讀事件觸發后可以按需收取想要的字節數,不用把本次數據收取干凈;
ET模式下,讀事件必須把數據收取干凈,因為我們不一定再有機會收取數據了。
2、LT模式下,不需要寫事件時一定要及時移除,避免不必要地觸發且浪費CPU資源。
ET模式下,寫事件觸發后,如果還需要下一次的寫事件觸發來驅動任務(例如發送上次剩余的數據),則我們需要繼續注冊一次檢測可寫事件
3、LT會導致多次觸發,ET優點是觸發次數少

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376807.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376807.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376807.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql中代替like模糊查詢的一種方法

使用Mysql的函數instr,可代替傳統的like方式查詢,并且速度更快。 instr函數&#xff0c;第一個參數是字段&#xff0c;第二個參數是要查詢的串&#xff0c;返回串的位置&#xff0c;第一個是1&#xff0c;如果沒找到就是0. 例如&#xff1a; select username from prefix_user …

兩種大小端判斷的方式

網絡通信是按照字節流進行數據交換的&#xff0c;主機根據不同的CPU型號可能是大段存儲&#xff0c;也可能是小端存儲。而網絡字節序在TCP/IP協議中已經規定好了&#xff0c;采用大端的排序方式。 所以網絡通信中一般將需要傳輸的整數型值轉換成網絡字節序。 從本機字節序轉換成…

把數據庫復制成腳本(包含遠程以及數據庫數據)

1.啟動VS 2.服務器資源管理器 3.連接需要的數據庫 4.右鍵數據庫 選擇publist to provider.... 5.剩下的 選擇數據庫 選擇存放地址 下一步 這方法應該是用在把08的數據還原到05上面 明天用這個方法去盜取哈公司的數據庫 看行不行轉載于:https://www.cnblogs.com/Rock-Lee/a…

代理模式用來初始化的延遲下載

package 設計模式; //代理模式實現延遲加載來減小啟動時間 //數據庫查詢接口 interface IDBQery{ public String request(); }class DBQuery implements IDBQery {//創建一個DBQery非常耗時的&#xff0c;這里面我可以在需要DBQuery的時候在創建public DBQuery(){try {Thread.s…

Linux網絡故障排查命令(ifconfig、ping、telnet、netstat、lsof、nc、curl、tcpdump)

目錄ifconfig-s&#xff0c;顯示網卡信息的精簡列表-a、up、down將IP地址綁定到某個網卡&#xff0c;以及解綁操作pingtelnetnetstatlsofnc模擬一個服務器程序和客戶端程序進行通信發送文件curltcpdump參數連接一個正常的監聽端口ifconfig 該命令用來查看當前系統的網卡和IP地…

My Oracle Support Metalink站點最近將放棄flash界面轉而使用ADF HTML

根據oracle官方博客的報道《The New My Oracle Support User Interface (HTML-based) 》&#xff0c; MY ORACLE SUPPORT開發team會在最近將support.oracle.com站點從原來的flash界面遷移到基于ADF HTML的用戶界面上。 實際上在2012年的 January 27&#xff0c; MOS開發team就…

BF算法

BF(Brute Force)算法是普通的模式匹配算法&#xff0c;BF算法的思想就是將目標串S的第一個字符與模式串T的第一個字符進行匹配&#xff0c;若相等&#xff0c;則繼續比較S的第二個字符和 T的第二個字符&#xff1b;若不相等&#xff0c;則比較S的第二個字符和T的第一個字符&…

心跳檢測以及應用層心跳包機制設計

博主聯系方式&#xff1a; QQ:1540984562 微信&#xff1a;wxid_nz49532kbh9u22 QQ交流群&#xff1a;750313950&#xff08;嵌入式方向&#xff09; QQ交流群&#xff1a;856398158&#xff08;后端方向&#xff09; 目錄心跳檢測應用場景死連接情況保活傳遞有效業務數據心跳包…

【APUE】孤兒進程與僵死進程

基本概念&#xff1a; 在unix/linux中&#xff0c;正常情況下&#xff0c;子進程是通過父進程創建的&#xff0c;子進程在創建新的進程。子進程的結束和父進程的運行是一個異步過程,即父進程永遠無法預測子進程 到底什么時候結束。 當一個 進程完成它的工作終止之后&#xff0c…

一個DBA的工作寫照

一個DBA的工作寫照&#xff0c; 一個DBA的內心 Know the DBA Mind! DBA也是 IT民工啊&#xff0c; 民工何苦為難民工&#xff01; 轉載于:https://www.cnblogs.com/macleanoracle/archive/2013/03/19/2968227.html

使用mutex和條件變量實現信號量

c提供了互斥量&#xff1a;mutex和條件變量&#xff1a;condition_variable&#xff0c;但是并沒有信號量&#xff1a;semaphore。而linux和windows系統庫會提供的。下面簡單介紹一下信號量的特性&#xff0c;然后給出一個簡單的demo&#xff0c;使用mutex condition_variable…

2014-07-28 使用Axure RP進行手機端BBS的原型設計

今天是在吾索實習的第14天。因本公司的微信公眾號需要有一個對外的技術交流平臺&#xff0c;所以我們小組打算設計一個手機端的BBS以滿足其要求。首先&#xff0c;我們需要做的是進行數據庫設計與原型設計&#xff0c;然后提交給經理驗收&#xff0c;看看是否合理&#xff0c;是…

jquery exif + lazyload實現延遲加載并顯示相片exif信息

對一個攝影愛好者來說&#xff0c;從高手的作品中學習是非常有用的。而照片的光圈&#xff0c;快門&#xff0c;感光度等信息是關注的重點。 上代碼&#xff1a; 1 <script src"../js/jquery.js" type"text/javascript"></script>2 <script…

undefined reference to `pthread_create‘(linux下Clion使用thread報錯)

完整報錯&#xff1a; [ Build | AsyncLogger | Debug ] /snap/clion/169/bin/cmake/linux/bin/cmake --build /home/dyy/CLionProjects/AsyncLogger/cmake-build-debug --target AsyncLogger -- -j 6 [ 50%] Linking CXX executable AsyncLogger /usr/bin/ld: CMakeFiles/Asy…

UVALive 6257 Chemist's vows --一道題的三種解法(模擬,DFS,DP)

題意&#xff1a;給一個元素周期表的元素符號&#xff08;114種&#xff09;&#xff0c;再給一個串&#xff0c;問這個串能否有這些元素符號組成&#xff08;全為小寫&#xff09;。 解法1&#xff1a;動態規劃 定義&#xff1a;dp[i]表示到 i 這個字符為止&#xff0c;能否有…

.NET開發相關使用工具和框架【轉載】

開發類 visual_studio 2005-2012系列----------語言開發工具 Visio 2003 / Power Desiger -----------建模工具 Dreamweaver_CS5 --------------網頁設計 ExpressionStudio 4 / blend 4 -------------wpf/silverlight設計工具 開發輔助類 SVN 主程序 ---------------文件控制 I…

JAVA數組的定義及用法

數組是有序數據的集合&#xff0c;數組中的每一個元素具有同樣的數組名和下標來唯一地確定數組中的元素。 1. 一維數組 1.1 一維數組的定義 type arrayName[]; type[] arrayName; 當中類型(type)能夠為Java中隨意的數據類型&#xff0c;包含簡單類型組合類型&#xff0c;數組名…

php操作httpsqs

php初始化httpsqs: include_once("httpsqs_client.php");$httpsqs new httpsqs("127.0.0.1", 1218, "mypass123", "utf-8"); php操作httpsqs:常用命令 操作入隊&#xff1a; $result $httpsqs->put(xiongwei2, test1); 獲取隊列中…

異步日志系統設計demo

目錄簡單版本1優化版本1優化版本2對于QPS要求很高或者對性能有一定要求的服務器程序&#xff0c;同步寫日志會對服務的關鍵性邏輯的快速執行和及時響應帶來一定的性能損失&#xff0c;因為寫日志時等待磁盤IO完成工作也需要一定時間。為了減少這種損失&#xff0c;一般采用異步…

js unix時間戳轉換

一、unix時間戳轉普通時間&#xff1a; var unixtime1358932051; var unixTimestamp new Date(unixtime* 1000); commonTime unixTimestamp.toLocaleString(); alert("普通時間為&#xff1a;"commonTime); 二、普通時間轉unix時間戳 var str "2013-01-01 00…