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.mzph.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…

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 安…

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…

线性规划在多种问题形式下的应用

线性规划的用处非常的广泛&#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;…

web学习笔记(二十一)

目录 1.构造函数创建对象 1.1规则 1.2 new关键字调用构造函数时&#xff0c;函数内部做了什么事情&#xff1f; 1.3总结 2.混合模式创建对象 3.JavaScript 继承---借助构造函数 4.原型链 4.1原型链实现方法继承 5.完美的组合继承 6.call方法的使用 1.构造函数创建对象…

React之数据绑定以及表单处理

一、表单元素 像<input>、<textarea>、<option>这样的表单元素不同于其他元素&#xff0c;因为他们可以通过用户交互发生变化。这些元素提供的界面使响应用户交互的表单数据处理更加容易 交互属性&#xff0c;用户对一下元素交互时通过onChange回调函数来监听…

回溯例题(leetcode17/37)

文章目录 leetcode37leetcode17 回溯跟枚举差不多。要注意“回溯”&#xff0c;别忘记“回”之前把之前的改动都复原。 leetcode37 leetcode37是解数独问题。本题保证有且仅有唯一解。 思路&#xff1a;先把空格子的位置存下来&#xff0c;然后对每一个空位置挨个枚举1-9。枚…

Excel常用公式总结非常实用

16个最实用的Excel万能公式 1、多条件判断 IF(And(条件1,条件2..条件N),条件成立返回值) IF(or(条件1,条件2..条件N),条件成立返回值) 2、多条件查找 Lookup(1,0/((条件1*条件2*...条件N)),返回值区域&#xff09; 3、多条件求和 Sumifs(值区域,判断区域1,条件1,判断区域2,条…

2024最新精华版Java面试题之spring篇

目录 一、Java面试题之spring篇 1、什么是spring? 2、你们项目中为什么使用Spring框架&#xff1f; 3、 Autowired和Resource关键字的区别&#xff1f; 4、依赖注入的方式有几种&#xff0c;各是什么? 5、讲一下什么是Spring容器&#xff1f; 6、说说你对Spring MVC的理…

Java毕业设计-基于springboot开发的私人健身与教练预约系统-毕业论文+答辩PPT(有源代码)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1.开发说明2.需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、后台功能模块2.1管理员功能2.2用户功能2.3教练功能 四、毕设内容和源代码获取总结 [Java毕业设计-基于springboot…

简单数据类型和复杂数据类型

1. 简单数据类型 null是个特例: 2. 复杂数据类型 3. 堆和栈 注意&#xff1a; JavaScript 中是没有堆和栈的概念的&#xff0c;通过堆栈的概念可以更好的理解代码的一些执行方式&#xff0c;便于将来学习其他语言。 4. 简单数据类型传参 总结&#xff1a;简单数据类型传参传…

在线ai写作,让你随时随地创作优质内容

如今的ai技术已经渗透到我们生活的方方面面。其中&#xff0c;AI写作成为了一个备受关注的领域。如今&#xff0c;我们可以利用在线ai写作在任何时间、任何地点创作出优质的内容。 传统的写作过程需要大量的时间和精力。从构思到写作再到修改&#xff0c;每一个环节都需要我们投…