IO多路復用 poll模型

poll 是一種在 Linux 系統中進行 I/O 多路復用的模型,它與 select 類似,但具有一些不同之處。poll 允許監視的文件描述符數量不受限制,而不像 select 有一定的限制。

基本概念:

  1. poll 函數: 通過 poll 函數,可以監視多個文件描述符的狀態。它使用 struct pollfd 結構體數組來描述要監視的文件描述符集合,并返回準備好讀、寫或發生錯誤的文件描述符的數量。

    #include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    
    • fds:一個指向 struct pollfd 結構體數組的指針,每個元素描述了一個要監視的文件描述符。
    • nfds:數組中元素的數量。
    • timeout:設置 poll 的超時時間,單位是毫秒。如果為負值,表示一直等待,如果為零,表示立即返回。
  2. struct pollfd 結構體: 用于描述單個文件描述符的狀態。

    struct pollfd {int   fd;        // 文件描述符short events;    // 要監視的事件(POLLIN、POLLOUT等)short revents;   // 實際發生的事件
    };
    

使用示例:

以下是一個簡單的使用 poll 進行 I/O 多路復用的示例:

#include <stdio.h>
#include <poll.h>int main() {struct pollfd fds[1];int timeout = 1000;  // 超時時間,單位是毫秒// 設置要監視的文件描述符fds[0].fd = // 你的文件描述符;fds[0].events = POLLIN;  // 監視可讀事件// 使用 poll 監視文件描述符int ready = poll(fds, 1, timeout);if (ready > 0) {if (fds[0].revents & POLLIN) {// 文件描述符可讀,處理數據}} else if (ready == 0) {// 超時} else {// 錯誤發生}return 0;
}

注意事項:

  1. poll 模型的優勢在于不受文件描述符數量的限制,但在高并發的場景中,可能仍需要考慮性能。

  2. pollselect 一樣,都是阻塞調用,可以通過設置超時時間為零或者使用非阻塞文件描述符來實現非阻塞調用。

  3. 可以使用 poll 的返回值來判斷文件描述符是否就緒,以及發生了哪些事件。

  4. poll 模型的使用和 select 相似,但在性能和可擴展性方面略有不同。在實際應用中,可以根據具體需求選擇適合的模型。

poll 函數使用的事件宏是定義在 poll.h 頭文件中的,這些宏表示 poll 可以監視的不同事件。下面是 poll 事件宏的一些常見值:

  1. POLLIN: 表示文件描述符可以讀取。如果設置了這個事件,表示數據可用于讀取。

    fds[0].events = POLLIN;
    
  2. POLLOUT: 表示文件描述符可以寫入。如果設置了這個事件,表示可以向文件描述符寫入數據。

    fds[0].events = POLLOUT;
    
  3. POLLPRI: 表示有緊急數據可讀。這通常是帶外數據或特殊條件的指示。

    fds[0].events = POLLPRI;
    
  4. POLLERR: 表示發生錯誤。如果設置了這個事件,表示文件描述符發生了錯誤條件。

    fds[0].events = POLLERR;
    
  5. POLLHUP: 表示文件描述符掛起。如果設置了這個事件,表示文件描述符被掛起(例如,對端關閉了連接)。

    fds[0].events = POLLHUP;
    
  6. POLLNVAL: 表示文件描述符不是一個打開的文件。如果設置了這個事件,表示文件描述符不是一個有效的打開文件。

    fds[0].events = POLLNVAL;
    

這些事件宏可以通過位運算進行組合,以監視多個事件。例如,同時監視可讀和可寫事件:

fds[0].events = POLLIN | POLLOUT;

在使用 poll 函數時,需要注意的是,revents 字段表示實際發生的事件,可以使用這個字段來判斷文件描述符發生了哪些事件。

if (fds[0].revents & POLLIN) {// 文件描述符可讀,處理數據
}if (fds[0].revents & POLLOUT) {// 文件描述符可寫,寫入數據
}// 其他事件的處理類似

這樣可以根據實際發生的事件來執行相應的操作。

在這里插入圖片描述

// 此程序演示采用poll模型實現網絡通訊的服務端#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/fcntl.h>using namespace std;int initserver(int port);int main (int argc, char *argv[])
{if(argc != 2){cout << "usage:./tcppoll port" << endl;return -1;}int listensock = initserver(atoi(argv[1]));if(listensock < 0) {cout << "initserver() failed" << endl; return -1;}pollfd fds[2048];for(int ii = 0; ii < 2048; ii ++ ) // 初始化全部socket為-1,poll會忽略值為-1的fds[ii].fd = -1;fds[listensock].fd = listensock; // socket和下標一一對應fds[listensock].events = POLLIN; // 只監視讀事件int maxfd = listensock;while(true){int infds = poll(fds, maxfd + 1, 10000); // 超時時間為10秒if(infds < 0) {perror("select() failed"); break; }if(infds == 0) {cout << "select() timeout." << endl; continue; }for(int eventfd = 0; eventfd <= maxfd; eventfd ++ ){if(fds[eventfd].fd < 0) continue;if((fds[eventfd].revents & POLLIN) == 0) continue; // 沒有讀事件,continueif(eventfd == listensock) // 如果發生事件的是監聽的socet,表示已連接隊列中有已經準備好的socket(有新的客戶端連上來了){struct sockaddr_in client;socklen_t len = sizeof(client);int clientsock = accept(listensock, (struct sockaddr*)&client, &len); // 調用一個客戶端連接if(clientsock < 0) {perror("accept() failed"); continue; }cout << "accept client(socket = " << clientsock << ")ok." << endl;fds[clientsock].fd = clientsock;fds[clientsock].events = POLLIN;if(maxfd < clientsock) maxfd = clientsock; // 整個if內代碼可以理解為如果有新的客戶端連上來,讓位圖對應位置標記為1}else // 如果是客戶端連接的socket有事件,表示接收緩存中有數據可以讀(對端發送的報文已到達),或者有客戶端已斷開連接{char buffer[1024];memset(buffer, 0, sizeof(buffer));if(recv(eventfd, buffer, sizeof(buffer), 0) <= 0) // 從接收緩沖區中讀取數據,<0已發生錯誤,=0表示斷開{cout << "client(eventfd = " << eventfd << ") disconnected." << endl;close(eventfd);fds[eventfd],fd = -1;if(eventfd == maxfd) // 關閉了當前的eventfd,應該重新設置maxfd{for(int ii = maxfd; ii > 0; ii ++ )if(fds[ii].fd != -1){maxfd = ii; break;}}}else // recv返回值大于0,表示對端發送的報文已到達,recv將返回成功讀取的字節數{cout << "recv(eventfd = " << eventfd << "): " << buffer << endl;send(eventfd, buffer, strlen(buffer), 0);} }}}return 0;}int initserver(int port)
{int sock = socket(AF_INET, SOCK_STREAM, 0);if(sock < 0){perror("socket() failed");return -1;}int opt = 1;unsigned int len = sizeof(opt);setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, len);struct sockaddr_in servaddr;servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(port);if(bind(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){perror("bind() failed");close(sock);return -1;}if(listen(sock, 5) != 0){perror("listen() failed");close(sock);return -1;}return sock;
}

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

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

相關文章

隊列的結構概念和實現

文章目錄 一、隊列的結構和概念二、隊列的實現三、隊列的實現函數四、隊列的思維導圖 一、隊列的結構和概念 什么是隊列&#xff1f; 隊列就是只允許在一端進行插入數據操作&#xff0c;在另一端進行刪除數據操作的特殊線性表&#xff0c;隊列具有先進先出 如上圖所示&#x…

【比較mybatis、lazy、sqltoy、mybatis-flex操作數據】操作批量新增、分頁查詢(二)

orm框架使用性能比較 環境&#xff1a; idea jdk17 spring boot 3.0.7 mysql 8.0比較mybatis、lazy、sqltoy、mybatis-flex操作數據 測試條件常規對象 orm 框架是否支持xml是否支持 Lambda對比版本mybatis????3.5.4sqltoy????5.2.98lazy????1.2.4-JDK17-SNAPS…

自定義 Python 程序參數解析

需要通過Python程序運行其它應用程序&#xff0c;程序格式為&#xff1a; 我的程序 <我的程序參數> 應用程序 <應用程序參數> 由于應用程序不固定&#xff0c;應用程序的參數也不固定&#xff0c;我的程序不需要對應用程序參數進行解析&#xff0c;僅需要解析自己的…

Vue+SpringBoot打造天然氣工程運維系統

目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 系統角色分類2.2 核心功能2.2.1 流程 12.2.2 流程 22.3 各角色功能2.3.1 系統管理員功能2.3.2 用戶服務部功能2.3.3 分公司&#xff08;施工單位&#xff09;功能2.3.3.1 技術員角色功能2.3.3.2 材料員角色功能 2.3.4 安…

快速冪-計算a的b次對m取余

題目 題解參考 a a ? a a a*a aa?a這部分是計算 a 2 i a^{2^i} a2i&#xff0c; a b Π i 0 t a n i 2 i Π i 0 t ( a 2 i ) n i a^b \Pi_{i0}^{t}a^{n_i 2^i} \Pi_{i0}^{t}(a^{2^i})^{n_i} abΠi0t?ani?2iΠi0t?(a2i)ni? ,代碼中的b&1是計算 n i n_i ni?…

Zabbix企業運維監控工具

Zabbix企業級監控方案 常見監控軟件介紹 Cacti Cacti是一套基于 PHP、MySQL、SNMP 及 RRD Tool 開發的監測圖形分析工具&#xff0c;Cacti 是使用輪詢的方式由主服務器向設備發送數據請求來獲取設備上狀態數據信息的,如果設備不斷增多,這個輪詢的過程就非常的耗時&#xff0…

sql注入less46作業三

采用報錯注入 updatexml(XML_document,XPath_string,new_value) 一共可以接收三個參數&#xff0c;報錯位置在第二個參數。 ?sort1 and updatexml(1,concat(0x7e,database(),0x7e),1)-- #查詢庫名 ?sort1 and updatexml(1,concat(0x7e,(select group_concat(table_name) fr…

[每周一更]-(第89期):開源許可證介紹

開源代碼本就是一種共享精神&#xff0c;一種大無畏行為&#xff0c;為了發揚代碼的魅力&#xff0c;創造更多的價值&#xff0c;讓愛傳遞四方&#xff0c;讓知識惠及更多人&#xff1b; 寫文章也是一種共享精神&#xff0c;讓知識傳播出去。 介紹下開源中不同許可證的內容限…

初學Vue總結

0 Vue概述 問題&#xff1a;我們已經學過了htmlCssjavascript,可以開發前端頁面了&#xff0c;但會發現&#xff0c;效率太低了。那么&#xff0c;有沒有什么工具可以提高我們的開發效率&#xff0c;加快開發速度呢&#xff1f; 他來了&#xff0c;他來了&#xff0c;他大佬似…

Spring注解之json 數據處理

目錄 1. 過濾 json 數據 2. 格式化 json 數據 3. 扁平化對象 1. 過濾 json 數據 JsonIgnoreProperties 作用在類上用于過濾掉特定字段不返回或者不解析。 //生成json時將userRoles屬性過濾 JsonIgnoreProperties({"userRoles"}) public class User { ?private S…

大宋咨詢如何進行汽車門店6S標準現場檢查

隨著汽車市場的快速發展&#xff0c;汽車門店的現場管理日益受到關注。6S標準現場檢查作為一項重要的評估工具&#xff0c;正在被越來越多的汽車廠商和經銷商采用。 6S標準現場檢查是指對汽車門店的整理、整頓、清潔、清掃、素養和安全六個方面進行規范和優化&#xff0c;旨在…

js中replaceAll在瀏覽器不兼容問題

前端項目有時候會出現瀏覽器使用replaceAll方法報錯問題&#xff0c;原因是一些舊版瀏覽器對replaceAll不是很兼容 解決辦法有三種&#xff1a; 1、str.replace(/word/g,“Excel”); g 的意義是&#xff1a;執行全局匹配&#xff08;查找所有匹配而非在找到第一個匹配后停止&am…

[AIGC] Java注解的生效時機詳解

在Java中&#xff0c;Annotation&#xff08;注解&#xff09;是一種用于描述代碼的元數據。它們可以為我們的代碼提供額外的信息&#xff0c;這些信息可以在編譯時或運行時被讀取。而注解的生效時機&#xff0c;主要由Java的Retention注解來控制。 一、注解的生效時機 Java中…

-XX:MaxTenuringThreshold

-XX:MaxTenuringThreshold&#xff0c;XX:PrintTenuringDistribution 虛擬機提供一個年齡&#xff0c;默認是15&#xff0c;對象超過這個年齡范圍就會晉升到老年代 【XX:PrintTenuringDistribution 可以輸出age的額外信息】 -XX:MaxTenuringThreshold -> https://www.jians…

線性規劃在多種問題形式下的應用

線性規劃的用處非常的廣泛&#xff0c;這主要是因為很多類型的問題是可以通過轉化的方式轉化為線性規劃的問題。例如需要再圖論中尋找起始點到給定的點的最短路徑問題&#xff1a; 添加圖片注釋&#xff0c;不超過 140 字&#xff08;可選&#xff09; 假設要計算從節點0到節點…

springboot配置多數據源以及事務問題

一、背景以及為什么需要學習 在高并發的項目中,單數據庫已無法承載大數據量的訪問,因此需要使用多個數據庫進行對數據的讀寫分離,此外就是在微服化的今天,我們在項目中可能采用各種不同存儲,因此也需要連接不同的數據庫,居于這樣的背景,這里簡單分享實現的思路以及實現…

點亮城市名片丨計訊物聯智慧燈桿系統在通訊基地的成功應用

項目背景 在國家新型城鎮化大背景下&#xff0c;十四五規劃綱要強調“加快數字化發展&#xff0c;建設數字中國”&#xff0c;明確提出“以數字化助推城鄉發展和治理模式創新”&#xff0c;全面提高城市的運行效率和宜居程度。 項目概況 為滿足燈桿燈光亮度的遠程智能管理、對…

記錄 android studio 通過安裝NDK 編譯C文件,得到需要的so文件

只怪自己太健忘&#xff0c;每次網上查了一圈&#xff0c;搞定后&#xff0c;再遇到又發現不會操作了&#xff0c;特此記下 不廢話直接上步驟 &#xff08;1&#xff09; 進入AS的settinging如下界面 &#xff08;2&#xff09;選中圖片箭頭兩個文件 進行下載 &#xff08;…

【知識管理】假設檢驗pvalue的計算

讓我們通過一個具體的例子來解釋P值的計算過程&#xff0c;假設我們有一個模型用于區分SCD&#xff08;亞臨床癡呆&#xff09;和HC&#xff08;健康對照&#xff09;的分裂。我們通過置換測試來計算模型性能的P值。 原始模型性能評估 首先&#xff0c;我們在原始數據集上運行…

web學習筆記(二十一)

目錄 1.構造函數創建對象 1.1規則 1.2 new關鍵字調用構造函數時&#xff0c;函數內部做了什么事情&#xff1f; 1.3總結 2.混合模式創建對象 3.JavaScript 繼承---借助構造函數 4.原型鏈 4.1原型鏈實現方法繼承 5.完美的組合繼承 6.call方法的使用 1.構造函數創建對象…