c++应用网络编程之十Linux下的Poll模式
一、Poll模式
在上一篇文章中提到了Select模式的缺点。既然有缺点,就要改正。但是直接在Select模式上修改不太现实,那么就推出一个新的模式不更香么?poll模式就应运而生了。不过,罗马不是一天建成的,poll模式也只是对select模式进行了局部的调优,仍然有着大幅改进的空间。
二、特点
poll模式的特点,基本和select模式一致。不同的是,通过自定义遍历fd的数组来解决了在select内核中很难改动的fd上限1024个(一般修改上限后需要重新编译内核)。这对于select来说,是一个巨大的进步。特别是对于一些监控客户端很多,但实际通信量并不多的场景下,其有着非常强的应用需求。
但是它的缺点仍然是select除此之外的未解决的问题。特别是在监听fd增大后,遍历所带来的开销进一步增大,所以一定要平衡好数量和效率的问题。所以产,poll可以认为是个过渡的模型。真正在实际应用中,一般很难看到。
同样需要说明的,它也可以用在客户端。不过一般一个客户端用这个就有点鸡肋了,除非有什么特别的要求。
三、数据结构和API
poll的数据结构也不复杂,看一下其相关代码:
#define POLLIN 0x0001 //普通或优先级带数据可读
#define POLLPRI 0x0002 //高优先级数据可读
#define POLLOUT 0x0004 //普通数据可写
#define POLLERR 0x0008 //错误
#define POLLHUP 0x0010 //挂起
#define POLLNVAL 0x0020 //描述字不是一个打开的文件/* The rest seem to be more-or-less nonstandard. Check them! */
#define POLLRDNORM 0x0040 //普通数据可读
#define POLLRDBAND 0x0080 //优先级带数据可读
#ifndef POLLWRNORM
#define POLLWRNORM 0x0100 //普通数据可写
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0x0200 //优先级带数据可写
#endif
#ifndef POLLMSG
#define POLLMSG 0x0400
#endif
#ifndef POLLREMOVE
#define POLLREMOVE 0x1000
#endif
#ifndef POLLRDHUP
#define POLLRDHUP 0x2000
#endif#define POLLFREE (__force __poll_t)0x4000#define POLL_BUSY_LOOP (__force __poll_t)0x8000struct pollfd {int fd;//监听的文件描述符short events;//该文件描述符的事件掩码,开发者设置short revents;//文件描述符的操作结果事件掩码,内核在调用返回时设置
};
一个pollfd对象代表着一个监听的文件描述符即Socket。如果需要监听多个Socket则需要创建一个pollfd对象数组通过接口函数poll进行处理。如果需要监听多类事件,则需要使用类似POLLIN | POLLRDNORM设置pollfd对象中events域。之后可以在调用poll接口后使用类似fds[i].revents & POLLIN的方法来检测相关事件是否发生,如果发生则可以进行相关事件的操作。
四、例程
poll的使用真心话,没有在实际的场景中使用过,所以只能简单的看一下代码:
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <atomic>using namespace std;
#define BUF_LEN 1024
#define FD_LEN 1000char DataBuf[BUF_LEN] = {0};class Poller
{
public:Poller();~Poller();int InitServer(unsigned short port = 8888);void Accept();void StartServer();void Recv();void Quit(){this->isRun = false;}
private:int listenFd = -1; struct pollfd fds[FD_LEN];int nfds = -1;bool isRun = true;struct sockaddr_in server_addr;socklen_t server_addr_len;
};Poller::Poller()
{
}Poller::~Poller()
{for(auto &fd:fds){if (fd>=0){shutdown(fd,2);close(fd);}}
}void Poller::InitServer(unsigned short port)
{bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htons(INADDR_ANY);server_addr.sin_port = htons(port);listenFd = socket(PF_INET, SOCK_STREAM, 0);if (listenFd < 0){perror("create socket err!");exit(1);}int opt = 1;setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));if (-1 == (bind(listenFd, (struct sockaddr *)&server_addr, sizeof(server_addr)))){perror("bind err!");exit(1);}if (-1 == listen(listenFd, 3)){perror("listen err!");exit(1);}
}void Poller::Accept()
{struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int clientFd = accept(listenFd, (struct sockaddr *)&client_addr, &client_addr_len);if (clientFd < 0){perror("poll accept error!");exit(1);}int count = 0;for (count = 1; count < FD_LEN; ++count){if (fds[count].fd < 0){fds[count].fd = clientFd;break;}}if (count == FD_LEN){perror("client is too much!");exit(1);}fds[count].events = POLLIN; nfds = count > nfds ? count : nfds;
}void Poller::StartServer()
{fds[0].fd = listenFd;fds[0].events = POLLIN;nfds = 0;for (int id = 1; id < FD_LEN; ++id){fds[id].fd = -1;}while (isRun){int nums = poll(fds, nfds + 1, -1);if (nums < 0){perror("poll err!");exit(1);}if (nums == 0){continue;}if (fds[0].revents & POLLIN){//fd 0 is listenAccept();}else{Recv()}}
}void Poller::Recv()
{for (int i = 1; i < FD_LEN; ++i){if (fds[i].fd < 0){continue;}//readif (fds[i].revents & POLLIN){int fd = fds[i].fd;bool isClosed = false;int len = 0;recv(fd, &len, sizeof(len), 0); // recv data lenmemset(DataBuf,0,len);int num = 0;while (num < len){int len = recv(fd, DataBuf + num, len - num, 0);if (len < 0){isClosed = true;break;}num = num + len;}if (num >= len){int ret = send(fd, DataBuf, len, 0);if (ret< 0){perror << "send data error!";isClosed = true;}}if (isClosed){shutdown(fd,2);close(fd);fds[i].fd = -1;}}}
}int main()
{Poller pollServer();pollServer.InitServer();pollServer.StartServer();gechar();return 0;
}
代码还是比较简单的,这里只给出服务端的代码,客户端如果大家感兴趣可以针对服务端简单修改一下即可。
五、总结
poll模式可以理解成一个从select优化的中间状态,改进了急需改进的问题但效率并未从根本上做出革命性的提高。这就给了大牛们继续创新和研究的空间,然后就引出来了后面的epoll和io_uring。
所以说,有需求就有前进的动力!
相关文章:
c++应用网络编程之十Linux下的Poll模式
一、Poll模式 在上一篇文章中提到了Select模式的缺点。既然有缺点,就要改正。但是直接在Select模式上修改不太现实,那么就推出一个新的模式不更香么?poll模式就应运而生了。不过,罗马不是一天建成的,poll模式也只是对…...
[C++][第三方库][RabbitMq]详细讲解
目录 1.介绍2.安装1.RabbitMq2.客户端库 3.AMQP-CPP 简单使用1.介绍2.使用 4.类与接口1.Channel2.ev 5.使用1.publish.cc2.consume.cc3.makefile 1.介绍 RabbitMQ:消息队列组件,实现两个客户端主机之间消息传输的功能(发布&订阅)核心概念࿱…...
Next.js 详解
Next.js是一个基于React的开源JavaScript框架,由Vercel(原Zeit)公司开发。它旨在简化React应用的构建过程,并提供了一系列强大的功能来优化性能和开发体验。以下是对Next.js的详细解析: 一、核心特性 服务器端渲染&…...
pygame--超级马里奥(万字详细版)
超级马里奥点我下载https://github.com/marblexu/PythonSuperMario 1.游戏介绍 小时候的经典游戏,代码参考了github上的项目Mario-Level-1,使用pygame来实现,从中学习到了横版过关游戏实现中的一些处理方法。原项目实现了超级玛丽的第一个小…...
【运维】nginx静态代理资源403权限问题
如题,遇到静态代理资源访问403,可以尝试检查其文件权限,父目录权限,需要确保 "目录使用标准的 755,对文件使用 644(umask:022)" 参考资料: 1. nginx “403 …...
java家政预约上门系统源码,家政服务平台源码,基于SpringBoot框架,数据库使用MySQL,界面渲染采用Thymeleaf技术开发
自主知识产权的家政预约上门系统源码,java版本,支持二次开发,适合商用上项目。 在这个快节奏的现代生活中,越来越多的家庭开始寻求高效、便捷的家政服务解决方案。传统的家政服务模式已经很难满足人们日益增长的个性化与即时性需求…...
算法知识点————贪心
贪心:只考虑局部最优解,不考虑全部最优解。有时候得不到最优解。 DP:考虑全局最优解。DP的特点:无后效性(正在求解的时候不关心前面的解是怎么求的); 二者都是在求最优解的,都有最优…...
python数据分析
Python是一种非常流行的编程语言,尤其在数据分析领域。Python拥有丰富的库和框架,可以帮助你执行各种数据分析任务。Python常用的数据分析工具之一:NumPy。 Numpy用于进行大规模数值和矩阵运算,提供了多维数组对象和一系列操作这…...
UGUI(现成组合控件)
Drop Down Scroll View Scroll Bar size是滚动条的填充程度 Slider 如果设置为静态,那么传入的值始终为自己设置的那个值 Input Field content type为standard时 可以设置line type, 只读不改,就是可以复制,但是你已经不能输入了…...
软件交付体系文件(Word源资料)
软件文档交付清单是指在软件开发项目完成后,开发团队需要准备的一份详细清单,用于确保交付的软件产品符合客户需求并达到预期的质量标准。以下是软件文档交付清单中可能包含的一些关键要素 软件全套资料部分文档清单: 工作安排任务书…...
【视频目标分割-2024CVPR】Putting the Object Back into Video Object Segmentation
Cutie 系列文章目录1 摘要2 引言2.1背景和难点2.2 解决方案2.3 成果 3 相关方法3.1 基于记忆的VOS3.2对象级推理3.3 自动视频分割 4 工作方法4.1 overview4.2 对象变换器4.2.1 overview4.2.2 Foreground-Background Masked Attention4.2.3 Positional Embeddings 4.3 Object Me…...
掌握 C# 文件和输入输出操作
在任何编程语言中,文件和输入输出操作(I/O)都是非常重要的组成部分。C# 提供了一系列工具和类来帮助开发者处理文件的读取、写入、二进制文件的处理以及数据的序列化与反序列化。本文将介绍 C# 中的文件操作,包括 File 类、Stream…...
k8s 中的金丝雀发布(灰度发布)
目录 1 什么是金丝雀发布 2 Canary 发布方式 3 Canary 两种发布方式实操 3.1 准备工作 3.1.1 将 nginx 命名两个版本 v1 与 v2 3.1.2 暴露端口并指定微服务类型 3.1.3 进入 pod 修改默认发布文件 3.1.4 测试 service 是否正常 3.2 基于权重的灰度发布 3.2.1 创建 Igress 资源类…...
《IDEA:让编程效率翻倍的强大工具》
哪个编程工具让你的工作效率翻倍? 在众多编程工具中,IntelliJ IDEA 无疑是一款让我的工作效率得到显著提升的利器。 一、功能特点 智能代码补全 IDEA 的代码补全功能极其智能。它不仅能根据你输入的前缀快速列出可能的代码选项,还会根据上…...
Docker 部署 Prometheus+Grafana 监控系统快速指南
Docker 部署 PrometheusGrafana 监控系统快速指南 文章目录 Docker 部署 PrometheusGrafana 监控系统快速指南一 创建网络二 监控部署三 配置 prometheus.yml四 测试部署是否成功五 Grafana表盘下载 本文详细介绍了通过 Docker 和 Docker Compose 快速部署 Prometheus 和 Grafa…...
No.8 笔记 | SQL 查询语句:数据探索的钥匙
2024/10/7 心记 - 致在路上默默奋斗的你 在当今数字化的时代,网络安全已成为我们生活中不可或缺的一部分。它如同守护数字世界的隐形盾牌,保护着我们的隐私、数据和整个社会的稳定运行。 学习网络安全,是踏上一段充满挑战与机遇的征程。 每一…...
全局数据在Python包中模块间管理方法探讨
在开发大型 Python 应用程序时,有时需要多个模块共享和管理全局数据。如何优雅地在 Python 包内的不同模块间共享全局数据是一个常见的设计问题。我们希望避免全局变量的混乱和难以维护的代码,但同时能够安全、高效地管理这些共享数据。 下面我们将探讨…...
无人机在矿业领域的应用!
矿区测绘与建模 无人机可以快速、全面地获取矿区的地形地貌数据,生成高精度的二维或三维模型。 这些模型可用于矿区的规划、设计、监测和管理,提高矿山的生产效率。 库存量量化监测 无人机能够捕捉厘米级的地形数据,通过计算得出准确的库…...
基于JavaWeb开发的java springmvc+mybatis学生考试系统设计和实现
基于JavaWeb开发的java springmvcmybatis学生考试系统设计和实现 🍅 作者主页 网顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各…...
【CKA】四、etcd的备份与恢复
4、etcd的备份与恢复 1. 考题内容: 2. 答题思路: 1、ssh到有etcdctl、etcdutl命令的节点 2、备份时注意添加证书并保证路径正确 3、备份完可以验证下 4、恢复备份时要停服务,恢复备份后重启kubelet 题型是一样的,我考的证书的路…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
