多路I/O转接 poll(了解)

news2024/11/19 16:47:21

        poll() 的机制与 select() 类似,与 select() 在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是 poll() 没有最大文件描述符数量的限制(但是数量过大后性能也是会下降)。 

        poll() 和 select() 同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。 

函数原型分析 

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

        fds:监听的文件描述符【数组

            struct pollfd {
                
                        int fd:    待监听的文件描述符
                
                        short events:    待监听的文件描述符对应的监听事件

                                                   取值:POLLIN、POLLOUT、POLLERR

                        short revnets:   传入时, 给0。如果满足对应事件的话,

                                                   返回 非0 -->POLLIN、POLLOUT、POLLERR
            }

        nfds: 监听数组的,实际有效监听个数。

        timeout:  > 0:  超时时长。单位:毫秒。

                         -1:    阻塞等待

                          0:  不阻塞

        返回值:返回满足对应监听事件的文件描述符总个数。

优缺点 

优点:
        自带数组结构。 可以将 监听事件集合 和 返回事件集合 分离

        拓展 监听上限。 超出 1024限制。

缺点:
        不能跨平台。 Linux

        无法直接定位满足监听事件的文件描述符, 编码难度较大。

代码实例

/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <errno.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666
#define OPEN_MAX 1024

int main(int argc, char *argv[])
{
	int i, j, maxi, listenfd, connfd, sockfd;
	int nready;
	ssize_t n;
	char buf[MAXLINE], str[INET_ADDRSTRLEN];
	socklen_t clilen;
	struct pollfd client[OPEN_MAX];
	struct sockaddr_in cliaddr, servaddr;

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	Listen(listenfd, 20);

	client[0].fd = listenfd;
	client[0].events = POLLRDNORM; 					/* listenfd监听普通读事件 */

	for (i = 1; i < OPEN_MAX; i++)
		client[i].fd = -1; 							/* 用-1初始化client[]里剩下元素 */
	maxi = 0; 										/* client[]数组有效元素中最大元素下标 */

	for ( ; ; ) {
		nready = poll(client, maxi+1, -1); 			/* 阻塞 */
		if (client[0].revents & POLLRDNORM) { 		/* 有客户端链接请求 */
			clilen = sizeof(cliaddr);
			connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
			printf("received from %s at PORT %d\n",
					inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
					ntohs(cliaddr.sin_port));
			for (i = 1; i < OPEN_MAX; i++) {
				if (client[i].fd < 0) {
					client[i].fd = connfd; 	/* 找到client[]中空闲的位置,存放accept返回的connfd */
					break;
				}
			}

			if (i == OPEN_MAX)
				perr_exit("too many clients");

			client[i].events = POLLRDNORM; 		/* 设置刚刚返回的connfd,监控读事件 */
			if (i > maxi)
				maxi = i; 						/* 更新client[]中最大元素下标 */
			if (--nready <= 0)
				continue; 						/* 没有更多就绪事件时,继续回到poll阻塞 */
		}
		for (i = 1; i <= maxi; i++) { 			/* 检测client[] */
			if ((sockfd = client[i].fd) < 0)
				continue;
			if (client[i].revents & (POLLRDNORM | POLLERR)) {
				if ((n = Read(sockfd, buf, MAXLINE)) < 0) {
					if (errno == ECONNRESET) { /* 当收到 RST标志时 */
						/* connection reset by client */
						printf("client[%d] aborted connection\n", i);
						Close(sockfd);
						client[i].fd = -1;
					} else {
						perr_exit("read error");
					}
				} else if (n == 0) {
					/* connection closed by client */
					printf("client[%d] closed connection\n", i);
					Close(sockfd);
					client[i].fd = -1;
				} else {
					for (j = 0; j < n; j++)
						buf[j] = toupper(buf[j]);
						Writen(sockfd, buf, n);
				}
				if (--nready <= 0)
					break; 				/* no more readable descriptors */
			}
		}
	}
	return 0;
}

read 函数

read 函数返回值:
        > 0: 实际读到的字节数

        =0: socket中,表示对端关闭。close()

        -1:    如果 errno == EINTR   被异常终端。 需要重启。

        如果 errno == EAGIN 或 EWOULDBLOCK 以非阻塞方式读数据,但是没有数据。  需要,再次读。

        如果 errno == ECONNRESET  说明连接被 重置。 需要 close(),移除监听队列。

        错误。 

(了解)突破1024 文件描述符限制 

cat /proc/sys/fs/file-max   -- >  当前计算机所能打开的最大文件个数。 受硬件影响。

ulimit -a     -- > 当前用户下的进程,默认打开文件描述符个数。  缺省为 1024

修改:
                打开 sudo vi /etc/security/limits.conf, 写入:

                * soft nofile 65536 --> 设置默认值,可直接借助命令修改【注销用户,使其生效】

                * hard nofile 100000  --> 命令修改上限。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 进阶(8) 线程常用方法

常用方法 方法名 说明 public static void sleep(long millis) 当前线程主动休眠 millis 毫秒。 public static void yield() 当前线程主动放弃时间⽚&#xff0c;回到就绪状态&#xff0c;竞争下⼀次时间⽚。 public final void join() 允许其他线程加⼊到当前线程中。…

什么是缓存穿透、缓存雪崩、缓存击穿

缓存穿透 缓存穿透 &#xff1a;缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库&#xff0c;失去了缓存保护后端存储的意义。 解决方案 缓存空值 如果访问数据库后还未命中&#xff0c;则把一…

JVM OOM问题排查与解决思路

OOM原因 1. 堆溢出 报错信息&#xff1a; java.lang.OutOfMemoryError: Java heap space 代码中可能存在大对象分配&#xff0c;无法获得足够的内存分配 可能发生内存泄露&#xff0c;导致内存被无效占用以至于耗尽 2. 永久代/元空间溢出 报错信息&#xff1a; java.lang.O…

Python黑马程序员(Spark实战)笔记

1、基础准备 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark # 导包 from pyspark import SparkConf,SparkContext #创建SparkConf类对象 confSparkConf().setMaster("local[*]").setAppName("test_spark_app") #基于SparkXConf类对象创…

(十一)排序算法-选择排序

1 基本介绍 选择排序也属于内部排序法&#xff0c;是从欲排序的数据中&#xff0c;按指定的规则选出某一元素&#xff0c;再依规定交换位置后达到排序的目的。 动画展示&#xff1a; 选择排序思想&#xff1a; 选择排序&#xff08;select sorting&#xff09;也是一种简单的…

【刷题篇】栈和队列

目录 一.前言&#x1f308; 二.有效的括号✨ a.题目 b.题解分析 c.AC代码 三. 用队列实现栈&#x1f4cf; a.题目 b.题解分析&#xff08;辅助队列法&#xff09; c.AC代码&#xff08;辅助队列法&#xff09; d.题解分析&#xff08;就地存储法&#xff09; c.AC代…

全面带你了解AIGC的风口

前言 一、AIGC的介绍 二、AIGC 的几个主要作用 三、实现AIGC过程的步骤 四、科技新赛道AIGC开始火了 五、AIGC对世界产生广泛的影响 六、AIGC技术的主要风口 &#x1f618;一、AIGC的介绍 AIGC (AI Generated Content) 是指通过人工智能技术生成的各种类型的内容&#xff0c;…

SpringBoot学习3

一、JSR303数据验证 使用Validated进行数据验证&#xff0c;如果数据异常则会统一抛出异常&#xff0c;方便异常中心统一处理。 空检查 Null 对象为null NotNull 对象不能为 null&#xff0c;但可以是 空字符串(无法检验长度为0的字符串) NotBlank 检查约束字符串是不是为nul…

20230403在WIN10下通过ffmpeg调用NVIDIA的硬件加速wmv视频转码为MP4格式

20230403在WIN10下通过ffmpeg调用NVIDIA的硬件加速wmv视频转码为MP4格式 2023/4/3 15:50 最近向学习日语&#xff0c;找到日语发音的视频中&#xff0c;大多数是MP4格式&#xff0c;少量是WMV格式&#xff0c;PR2023貌似不能识别WMV格式。 于是&#xff1a;万能的ffmpeg上场了&…

使用GPT-4生成QT代码

一、概述最近ChatGPT火爆起来了&#xff0c;ChatGPT是一种基于GPT的自然语言处理模型&#xff0c;可以用于生成自然语言文本&#xff0c;例如对话、文章等。最近又发现了一个优秀且免费的代码生成工具Cursor &#xff0c;Cursor集成了 GPT-4 &#xff0c;可以帮助你快速编写、编…

动态规划:状态机DP和买卖股票问题【零神基础精讲】

买卖股票的最佳时机&#xff1a;无限次/冷冻期/k次【基础算法精讲 21】 来自0x3f&#xff1a;https://www.bilibili.com/video/BV1ho4y1W7QK/ 介绍了【买卖股票系列问题】与【状态机 DP】&#xff0c;包括【至多/恰好/至少】的讲解。 文章目录买卖股票问题和状态机DP(无限次)[1…

【CocosCreator入门】CocosCreator组件 | DragonBones(骨骼动画)组件

Cocos Creator 是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中DragonBones&#xff0c;它可以帮助您创建出色的2D骨骼动画。在本文中&#xff0c;我们将探讨CocosCreator引擎的DragonBones组件&#xff0c;以及如何使用它来创建精美的动画。 目录 …

VisualGC插件使用

下载安装VisualVM 下载地址&#xff1a;Visual VM mac系统选择macOS Application Bundle&#xff0c;下载完成后&#xff0c;双击dmg包安装即可&#xff0c;之后双击启动。 安装Visual GC 插件 点击菜单栏Tools&#xff0c;选择Pulgins&#xff0c;在第二个选项中找到Visua…

【CSS】更改用户界面样式 ③ ( 取消文本域拖拽 | 代码示例 )

文章目录一、取消文本域拖拽二、文本域拖拽示例三、取消文本域拖拽示例一、取消文本域拖拽 textarea 文本域 在 默认状态下是可以进行拖拽的 , 在网页布局中 , 一般不会允许这种情况发生 , 任意拖拽文本域会影响网页的整体布局 ; 设置文本域不可拖拽样式 : resize: none;文本…

windows编程(4) - GDI绘图基础

基础概念 GDI&#xff1a;Graphic Device Interface 图形设备接口。GUI&#xff1a;Graphic User Interface 图形用户接口。HDC&#xff1a;Handle of Device Context&#xff1a; 图形设备上下文句柄。 字符界面的基本单位是字符。 图形界面的基本单位是像素。 像素&#…

从数据展示中汉字缺失了解字符编码知识

有人在使用皕杰报表时遇到如下问题&#xff1a; 有些汉字变成了“&#xff1f;”&#xff0c;这是为什么呢&#xff1f;实际上就是你用的字符集里没有这个汉字导致的&#xff0c;要想搞懂这个问题&#xff0c;还得从字符、字符集、字符编码说起。 所谓字符&#xff0c;就是各…

定时任务练习----Linux 定时发送邮件 ( QQ 邮箱 为例)

邮件设置 &#xff1a; 在 QQ 邮箱的最上面 &#xff0c;点击设置。 在账户 这一栏&#xff0c;往下面走 找POP3 开头的栏目 在 POP3/SMTP 服务这一行&#xff0c;点击开启 &#xff08; 本身是 关闭状态 &#xff09; 关于 POP3 和 SMTP 服务需要做以说明 ; >>> 我…

技术管理笔记1

看点杂篇&#xff0c;整理下笔记&#xff1a; 目录&#xff1a; 1技术的本质 2 技术团队管理的本质 3 技术管理者的能力要求 4 技术管理者风格类型 5 实战案例分析&#xff1a; 一技术的本质 技术存在感低&#xff0c;缺乏话语权&#xff0c;以业务导向为主。 二 技术团…

Spring Cloud第二季--OpenFeign和Feign

文章目录一、Feign二、Feign和OpenFeign的区别三、案例测试1、eureka注册中心集群7001/70022、两个微服务3、OpenFeign一、Feign Spring Cloud Feign的介绍在Spring Cloud学习–声明式调用&#xff08;Feign&#xff09;中详细介绍。 简单回顾下&#xff0c;Feign是一个声明式…

UTF-8(Unicode Transformation Format)

文章目录一、Unicode示例代码&#xff1a;二、网络传输与Unicode三、UTF-8如何编码四、使用UTF-8转换传输Unicode五、利用Java-API进行UTF8编码和解码六、利用代码输出Unicode编码和UTF8编码七、手写UTF8编码、解码八、总结UTF8一、Unicode 示例代码&#xff1a; package demo…