Linux高级IO之poll

 (。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~icon-default.png?t=N7T8https://blog.csdn.net/ky233?type=blog

点个关注不迷路⌯'▾'⌯

目录

一、poll函数接口

1.接口

2.poll做了什么工作

3.events和revents的取值

二、代码

三、poll的优缺点


poll将输入参数和输出参数做了分离,所以我们就不用对参数进行重新设定了。并且把上限取消了 

一、poll函数接口

1.接口

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
// pollfd结构
struct pollfd {int fd; /* file descriptor */short events; /* requested events */short revents; /* returned events */
}

参数说明:

  1. fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返 回的事件集合.
  2. nfds表示fds数组的长度.
  3. timeout表示poll函数的超时时间, 单位是毫秒(ms).

2.poll做了什么工作

poll只负责等!

1.用户告诉内核:你帮我关心,哪些fd,哪些事件

2.内核告诉用户:哪些fd,哪些时间已经就绪了

3.events和revents的取值

二、代码

#ifndef __POLL_SVR_H__
#define __POLL_SVR_H__#include <iostream>
#include <string>
#include <vector>
#include <poll.h>
#include <sys/time.h>
#include "Log.hpp"
#include "Sock.hpp"#define FD_NONE -1using namespace std;
// select 我们只完成读取,写入和异常不做处理 -- epoll(写完整)
class PollServer
{
public:static const int nfds = 100;
public:PollServer(const uint16_t &port = 8080) : _port(port), _nfds(nfds){_listensock = Sock::Socket();Sock::Bind(_listensock, _port);Sock::Listen(_listensock);logMessage(DEBUG,"%s","create base socket success");_fds = new struct pollfd[_nfds];for(int i = 0; i < _nfds; i++) {_fds[i].fd = FD_NONE;_fds[i].events = _fds[i].revents = 0;}_fds[0].fd = _listensock;_fds[0].events = POLLIN;_timeout = 1000;}void Start(){while (true){int n = poll(_fds, _nfds, _timeout);switch (n){case 0:logMessage(DEBUG, "%s", "time out...");break;case -1:logMessage(WARNING, "select error: %d : %s", errno, strerror(errno));break;default:// 成功的HandlerEvent();break;}}}~PollServer(){if (_listensock >= 0)close(_listensock);if (_fds) delete [] _fds;}
private:void HandlerEvent() // fd_set 是一个集合,里面可能会存在多个sock{for(int i = 0; i < _nfds; i++){// 1. 去掉不合法的fdif(_fds[i].fd == FD_NONE) continue;// 2. 合法的就一定就绪了?不一定if(_fds[i].revents & POLLIN){//指定的fd,读事件就绪// 读事件就绪:连接事件到来,acceptif(_fds[i].fd == _listensock) Accepter();else Recver(i);}}}void Accepter(){string clientip;uint16_t clientport = 0;// listensock上面的读事件就绪了,表示可以读取了// 获取新连接了int sock = Sock::Accept(_listensock, &clientip, &clientport); // 这里在进行accept会不会阻塞?不会!if(sock < 0){logMessage(WARNING, "accept error");return;}logMessage(DEBUG, "get a new line success : [%s:%d] : %d", clientip.c_str(), clientport, sock);int pos = 1;for(; pos < _nfds; pos++){if(_fds[pos].fd == FD_NONE) break;}if(pos == _nfds){// 对struct pollfd进行自动扩容logMessage(WARNING, "%s:%d", "poll server already full,close: %d", sock);close(sock);}else{_fds[pos].fd = sock;_fds[pos].events = POLLIN;}}void Recver(int pos){// 读事件就绪:INPUT事件到来、recv,readlogMessage(DEBUG, "message in, get IO event: %d", _fds[pos]);// 暂时先不做封装, 此时select已经帮我们进行了事件检测,fd上的数据一定是就绪的,即 本次 不会被阻塞// 这样读取有bug吗?有的,你怎么保证以读到了一个完整包文呢?char buffer[1024];int n = recv(_fds[pos].fd, buffer, sizeof(buffer)-1, 0);if(n > 0){buffer[n] = 0;logMessage(DEBUG, "client[%d]# %s", _fds[pos].fd, buffer);}else if(n == 0){logMessage(DEBUG, "client[%d] quit, me too...", _fds[pos].fd);// 1. 我们也要关闭不需要的fdclose(_fds[pos].fd);// 2. 不要让select帮我关心当前的fd了_fds[pos].fd = FD_NONE;_fds[pos].events = 0;}else{logMessage(WARNING, "%d sock recv error, %d : %s", _fds[pos].fd, errno, strerror(errno));// 1. 我们也要关闭不需要的fdclose(_fds[pos].fd);// 2. 不要让select帮我关心当前的fd了_fds[pos].fd = FD_NONE;_fds[pos].events = 0;}}void DebugPrint(){cout << "_fd_array[]: ";for(int i = 0; i < _nfds; i++){if(_fds[i].fd == FD_NONE) continue;cout << _fds[i].fd << " ";}cout << endl;}
private:uint16_t _port;int _listensock;struct pollfd *_fds;int _nfds;int _timeout;
};#endif

三、poll的优缺点

优点:

  1. 效率高,和select一样
  2. 节省资源,有大量的连接,只有少量是活跃的
  3. 输入和输出参数分离,不需要大量的重置
  4. 参数级别没有fd的上限

缺点:

  1. poll还是需要遍历,而且不少,在用户层检测时间就绪,与在内核层检测fd就绪,都是一样的
  2. poll需要用户和内核进行拷贝只需要进行一次,但内核到用户需要一直拷贝,这个时少不了的
  3. poll编写也不太容易,但比select容易

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/526388.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++程序设计-第六/七/八章 运算符重载/包含与继承/虚函数和多态性【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下C程序设计中的重点概念&#xff0c;以供大家期末复习和考研复习的时候使用。 C程序设计系列文章传送门&#xff1a; 第一章 面向对象基础 第四/五章 函数和类和对象 第六/七/八章 运算符重载/包含与继承/虚函…

《探索虚拟与现实的边界:VR与AR谁更能引领未来?》

引言 在当今数字时代,虚拟现实(VR)和增强现实(AR)技术正以惊人的速度发展,并逐渐渗透到我们的日常生活中。它们正在重新定义人与技术、人与环境之间的关系,同时也为各行各业带来了全新的可能性。然而,究竟是VR还是AR更有潜力改变未来?本文将围绕这一问题展开深入探讨。…

Canal安装使用

一 Canal介绍 canal是阿里巴巴旗下的一款开源项目&#xff0c;纯Java开发。基于数据库增量日志解析&#xff0c;提供增量数据订阅&消费&#xff0c;目前主要支持了MySQL&#xff08;也支持mariaDB&#xff09;。 背景 早期&#xff0c;阿里巴巴B2B公司因为存在杭州和美国…

少儿编程 蓝桥杯青少组科技素养题 信息素养真题及解析第25套

少儿编程 科技素养 信息素养真题第25套 1、旅行结束之后&#xff0c;回到家的小蓝决定将照片备份在云端的网盘上。备份照片主要占用的是小蓝家的( )带宽 A、下行 B、上行 C、文件 D、数据 答案&#xff1a;B 考点分析&#xff1a;主要考查网络相关知识&#xff0c;要将照…

公众号IP白名单已添加服务器IP 122.88... 依然给出 40164 错误

公众号的IP白名单已添加 122.88... 依然给出 40164 错误。 {"errcode":40164,"errmsg":"invalid ip 122.88... ipv6 ::ffff:122.88..., not in whitelist rid: 65e85a07-458dfc0d-16003e03"} 解决方案&#xff1a; 一、检查 AppID 是否正确&…

【数学】【组合数学】1830. 使字符串有序的最少操作次数

作者推荐 视频算法专题 本博文涉及知识点 数学 组合数学 LeetCode1830. 使字符串有序的最少操作次数 给你一个字符串 s &#xff08;下标从 0 开始&#xff09;。你需要对 s 执行以下操作直到它变为一个有序字符串&#xff1a; 找到 最大下标 i &#xff0c;使得 1 < i…

Javaweb之Maven高级之继承的详细解析

2.1 继承 我们可以再创建一个父工程 tlias-parent &#xff0c;然后让上述的三个模块 tlias-pojo、tlias-utils、tlias-web-management 都来继承这个父工程 。 然后再将各个模块中都共有的依赖&#xff0c;都提取到父工程 tlias-parent中进行配置&#xff0c;只要子工程继承了…

C++单例模式、工厂模式

一、单例模式 (一) 什么是单例模式 1. 是什么&#xff1f; 在系统的整个生命周期内&#xff0c;一个类只允许存在一个实例。 2. 为什么&#xff1f; 两个原因&#xff1a; 节省资源。方便控制&#xff0c;在操作公共资源的场景时&#xff0c;避免了多个对象引起的复杂操作…

云原生之容器编排实践-ruoyi-cloud项目部署到K8S:Nginx1.25.3

背景 前面搭建好了 Kubernetes 集群与私有镜像仓库&#xff0c;终于要进入服务编排的实践环节了。本系列拿 ruoyi-cloud 项目进行练手&#xff0c;按照 MySQL &#xff0c; Nacos &#xff0c; Redis &#xff0c; Nginx &#xff0c; Gateway &#xff0c; Auth &#xff0c;…

异步编程实战:使用C#实现FTP文件下载及超时控制

博客标题: 异步编程实战&#xff1a;使用C#实现FTP文件下载及超时控制 如果你的函数不是async&#xff0c;你仍然可以实现相同的超时功能&#xff0c;但你将不得不依赖更多的同步代码或使用.Result或.GetAwaiter().GetResult()来阻塞等待任务完成&#xff0c;这可能导致死锁的风…

mybatis-plus整合spring boot极速入门

使用mybatis-plus整合spring boot&#xff0c;接下来我来操作一番。 一&#xff0c;创建spring boot工程 勾选下面的选项 紧接着&#xff0c;还有springboot和依赖我们需要选。 这样我们就创建好了我们的spring boot&#xff0c;项目。 简化目录结构&#xff1a; 我们发现&a…

uniapp 解决请求出现 /sockjs-node/info?t=问题

1. uniapp请求出现 /sockjs-node/info?t问题 1.1. 问题 uniapp项目老是出现 http://192.168.2.106:8080/sockjs-node/info?t1709704280949 1.1. sockjs-node介绍 sockjs-node 是一个JavaScript库&#xff0c;提供跨浏览器JavaScript的API&#xff0c;创建了一个低延迟、全…