多路转接之poll(接口介绍,struct pollfd介绍,实现原理,实现非阻塞网络通信代码)
目录
poll
引入
介绍
函数原型
fds
struct pollfd
特点
nfds
timeout
取值
返回值
原理
如何实现关注多个fd?
如何确定哪个fd上有事件就绪?
如何区分事件类型?
判断某事件是否就绪的方法
代码
示例
总结
为什么说它解决了fd上限问题?
缺点
poll
引入
我们前面介绍了select -- 多路转接之select(fd_set介绍,参数详细介绍,优缺点),实现非阻塞式网络通信(代码+思路)-CSDN博客
- 随着文件数量增多(有新客户端来连接),文件上事件就绪的概率也就增大了
- 而等待就绪->通知用户层有事件就绪的过程涉及到多次遍历和拷贝,就绪次数多了,遍历和拷贝就多了
- 所以,会慢慢让效率变低
为了解决这些问题,出现了新的多路转接的方案 -- poll
介绍
是一种用于多路复用 I/O 事件的系统调用,它允许程序监视多个文件描述符,并等待其中的某些事件发生
- 它和select一样,只负责等待
- 它主要解决了select的两个弊端 -- fd有上限 和 参数重置问题
函数原型

fds
和select中三个位图的作用相同 -- 用于用户和内核之间的信息交流,但原理不同
struct pollfd
- 用户给内核传入要关注文件的fd和要关注的事件类型 -- 使用了pollfd中的fd,events字段
- 内核给用户返回该文件上的哪个事件已就绪 -- 使用fd,revents字段
特点
将输入和输出事件分离
- 而不是像select一样,用户和内核使用的是同一个结构(位图)
- 这里使用了两个变量给两方分别使用
nfds
fds中的元素个数
- 相当于需要关注的fd个数
timeout
等待事件的超时时间
- 以毫秒为单位,1000ms=1s
取值
- >0 -- 超时时间
- =0 -- 非阻塞,函数会立即返回
- -1
返回值
和select作用相同
- >0 -- 就绪的fd个数
- =0 -- 超时,没有事件就绪
- <0 -- 等待的文件中有已经关闭的文件
原理
如何实现关注多个fd?
这里的fds参数是一个结构体类型的指针
- 所以可以传入结构体数组 / 指向堆上空间的指针,后续可以动态扩容
所以,我们可以添加多个pollfd结构到数组中
如何确定哪个fd上有事件就绪?
遍历数组,检查每个结构的revents字段状态
如何区分事件类型?
将events/revents字段看作16个bit位,1个bit位可以对应一个事件类型
- 和标志位一样
判断某事件是否就绪的方法
- 以读事件为例:
- (某个指定pollfd结构中的revents & POLLIN) 是否等于1,等于1说明该事件已经就绪
代码
我们可以直接改select代码为poll版本,很简单:
- 不需要在循环内重复设置参数
- 把那些删掉后,修改调用select为poll即可,最多就创建一个pollfd结构体
#include "Log.hpp"
#include "socket.hpp"
#include <poll.h>static const int def_port = 8080;
static const int def_max_num = 1024;
static const int def_data = -1;
static const int no_data = 0;class poll_server
{
public:poll_server(){for (int i = 0; i < def_max_num; ++i){fds_[i].fd = def_data;fds_[i].events = no_data;fds_[i].revents = no_data;}}~poll_server(){listen_socket_.Close();}void start(){listen_socket_.Socket();listen_socket_.Bind(def_port);listen_socket_.Listen();int timeout = 1;// 固定数组第一项是监听套接字struct pollfd tl = {listen_socket_.get_fd(), POLLIN, no_data};fds_[0] = tl;while (true){int ret = poll(fds_, def_max_num, timeout);if (ret > 0) // 有事件就绪{handle();}else if (ret == 0) // 超时{continue;}else{perror("poll");break;}}}private:void receiver(int fd, int i){char in_buff[1024];int n = read(fd, in_buff, sizeof(in_buff) - 1);if (n > 0){in_buff[n - 1] = 0;std::cout << "get message: " << in_buff << std::endl;}else if (n == 0) // 客户端关闭连接{close(fd);lg(DEBUG, "%d quit", fd);fds_[i].fd = -1; // 重置该位置fds_[i].events = no_data;fds_[i].revents = no_data;}else{lg(ERROR, "fd: %d ,read error");}}void accepter(){std::string clientip;uint16_t clientport;int sock = listen_socket_.Accept(clientip, clientport);if (sock == -1){return;}else // 把新fd加入数组{struct pollfd t;int pos = 1000; //1sfor (; pos < def_max_num; ++pos){if (fds_[pos].fd == def_data) // 找到空位,但不能直接添加{break;}}if (pos != def_max_num){t.fd = sock;}else // 满了{//这里可以扩容lg(WARNING, "server is full,close %d now", sock);close(sock);}t.events = POLLIN;t.revents = no_data;fds_[pos] = t;}}void handle(){for (int i = 0; i < def_max_num; ++i) // 遍历数组{int fd = fds_[i].fd;if (fd != def_data) // 有效fd{if (fds_[i].revents & POLLIN) // 有事件就绪{if (fd == listen_socket_.get_fd()) // 获取新连接{accepter();}else // 读事件{receiver(fd, i);}}}}}private:MY_SOCKET listen_socket_;struct pollfd fds_[def_max_num];
};
示例
总结
为什么说它解决了fd上限问题?
因为poll里的数组大小由用户决定,而fd_set的大小已经被系统定死了,无法改变
缺点
但是,poll依然没有解决多次遍历的问题
- 用户层需要查看数组中每个结构的revents,看哪些文件的哪些事件就绪了
- 内核也需要遍历数组,查看需要关注哪些文件的哪些事件,查看是否有文件就绪
遍历成本由文件个数决定
- 虽然poll没有限制,但一旦数量过多,会影响遍历效率
所以,为了解决这个问题,提出了新的方案 -- epoll
它是目前效率最高的多路转接方案
相关文章:
多路转接之poll(接口介绍,struct pollfd介绍,实现原理,实现非阻塞网络通信代码)
目录 poll 引入 介绍 函数原型 fds struct pollfd 特点 nfds timeout 取值 返回值 原理 如何实现关注多个fd? 如何确定哪个fd上有事件就绪? 如何区分事件类型? 判断某事件是否就绪的方法 代码 示例 总结 为什么说它解决了fd上限问题? 缺点 poll 引入…...
两个月冲刺软考——位示图题型的例题讲解与分析;索引文件的详细解读
1. 位示图 位示图(Bitmap)是一种数据结构,用于表示和存储图像信息。在计算机科学中,位示图通常指的是一个二维的数组,每个元素称为一个像素,每个像素可以存储一个颜色值。 可以将位示图类比为电影院选座操作…...
SprinBoot+Vue校园数字化图书馆系统的设计与实现
目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…...
python如何加速计算密集型任务?
问题描述: 在python中,有一个函数,其功能是进行某种计算,需要传入一些参数,计算完成后传回结果,调用其一次大概要1s的时间,现在需要通过for循环调用其350次,保存每次调用结果&#…...
握手的方式展现人的性格及行为倾向
握手是人际交往中最常见的礼节之一,同时通过和对方握手,可以感知他的内心,进一步得知对方的性格及行为倾向。 心理学家认为,最好的握手方式是力度适中,动作沉稳,自然注视对方的眼睛,这种握手方…...
Java 排序算法详解
排序是计算机科学中的基本操作,Java 提供了多种排序算法来满足不同的需求。常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序和堆排序。本文将逐一介绍这些排序算法及其 Java 实现。 1. 冒泡排序 (Bubble Sort) 冒泡排序是一种简单的排序算法…...
vue3实现拖拽移动位置,拖拽过程中鼠标松开后元素还吸附在鼠标上并随着鼠标移动
发现问题 拖拽元素移动的时候,偶尔会出现拖拽过程中鼠标松开后元素还吸附在鼠标上并随着鼠标移动,要再按一下元素才会被放置下来。但是有时就正常。 问题分析 出现该问题的原因是:这个过程会触发H5原生的拖拽事件,并且不会监听…...
没有屋檐的房子-011
棺材 (下) 时过境迁这个成语描述了前因后果的两种概念的变化,时间推延和环境的变迁。问题是,时间是什么呢?是环境变化表征了时间的推延,还是时间推延导致了环境的变化?人在多数时候,…...
Puppeteer-Cluster:并行处理网页操作的新利器
在现代Web开发和自动化测试领域,高效地处理多个网页操作任务成为了许多开发者和测试工程师的迫切需求。传统的Puppeteer工具虽然功能强大,但在处理大量并发任务时可能会显得力不从心。为此,Puppeteer-Cluster应运而生,作为一个基于…...
使用Protocol Buffers传输数据
使用 Google Protocol Buffers(ProtoBuf)与 Kafka 结合来定义和传输数据,可以确保传输数据的结构性、可扩展性和高效性。以下是一个简单的步骤指南,帮助你实现生产者和消费者。 1. 定义 ProtoBuf 消息格式 首先,你需…...
chmod修改文件权限
0 Preface/Foreword 1 chmod使用方法 1.1 修改单个文件 命令如下: sudo chmod xyz fileName xyz: x, y, z分别代表一个8进制数字(0-7) 1.2 修改文件夹 命令如下: sudo chmod -R xyz folderName...
二叉树--python
二叉树 一、概述 1、介绍 是一种非线性数据结构,将数据一分为二,代表根与叶的派生关系,和链表的结构类似,二叉树的基本单元是结点,每个节点包括值和左右子节点引用。 每个节点都有两个引用(类似于双向链…...
matlab数据批量保存为excel,文件名,行和列的名称设置
Excel文件内数据保存结果如下: Excel文件保存结果如下: 代码如下: clear;clc; for jjjj1:10 %这个可以改 jname(jjjj-1)*10; %文件名中变数 这是EXCEL文件名字的一部分 根据自己需要改 jkkkk_num2str(jname); for …...
Pygame中Sprite类实现多帧动画3-2
3.2.3 设置帧的宽度、高度、范围及列数 通过如图6所示的代码设置帧的宽度、高度、范围及列数。 图6 设置帧的宽度、高度、范围及列数的代码 其中,frame_width、frame_height、rect和columns都是MySprite类的属性,在其__init__()方法中定义,…...
C#发送正文带图片带附件的邮件
1,开启服务,获取授权码。以QQ邮箱为例: 点击管理服务,进入账号与安全页面 2,相关设置参数,以QQ邮箱为例: 登录时,请在第三方客户端的密码输入框里面填入授权码进行验证。࿰…...
【C#跨平台开发详解】C#跨平台开发技术之.NET Core基础学习及快速入门
1. C#与.NET的发展历程 C#是由Microsoft开发的现代编程语言,最初伴随着.NET Framework发布。随着技术的进步,特别是针对跨平台开发的需求,Microsoft推出了.NET Core,这是一个开源且跨平台的框架,支持Windows、macOS和…...
请解释Java中的死锁产生的原因和解决方法。什么是Java中的并发工具类?请列举几个并解释其用途。
请解释Java中的死锁产生的原因和解决方法。 Java中的死锁是指两个或两个以上的线程在执行过程中,因为争夺资源而造成的一种相互等待的现象,若无外力作用,这些线程都将无法向前推进。死锁是并发编程中常见的问题,它会导致程序运行…...
三分钟带你看懂,低代码开发赋能办公方式转变
随着技术的不断进步,企业对办公效率和灵活性的需求日益增长。低代码开发作为一种新兴的开发模式,正在改变传统的办公方式,让非技术背景的业务人员也能参与到应用的创建和维护中来。本文将带你快速了解低代码开发如何赋能办公方式的转变。 什么…...
视频剪辑软件哪个好用?11款软件轻松上手,让创意视频流畅呈现!
视频剪辑已经涉及到很多个领域,视频剪辑软件的需求也是越来越普遍了。很多朋友在日常办公学习中,经常会遇到视频剪辑的问题。借助专业的视频剪辑软件,我们可以快速的对视频进行剪辑,制作出属于自己的作品。 市面上有各种各样的视频…...
pytest二次开发:生成用例参数
pytest.fixture是一个装饰器,用于声明一个fixture。Fixture是pytest中的一个核心概念,它提供了一种将测试前的准备代码(如设置测试环境、准备测试数据等)和测试后的清理代码(如恢复测试环境、删除临时文件等࿰…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
.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 适用场…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...


