Linux I/O复用函数的使用情况和select接口的介绍
I/O 复用使得程序能同时监听多个文件描述符,这对于提高程序的性能至关重要。通常,
网络程序在下列情况下需要使用 I/O 复用技术:
1.TCP服务器同时要处理监听套接字和连接套接字2.服务器同时要处理TCP请求和UDP请求。
3.程序同时要处理多个套接字。
4.客服端程序要同时处理用户输入和网络连接。
5.服务器要同时监听多个端口。
需要指出的是, I/O 复用虽然能同时监听多个文件描述符,但它本身是阻塞的。并且当
多个文件描述符同时就绪时,如果不采取额外的措施,程序就只能按顺序依处理其中的每一
个文件描述符,这使得服务器看起来好像是串行工作的。如果要提高并发处理的能力,可以
配合使用多线程或多进程等编程方法。
1select
1.1select的接口介绍
select系统调用的用途是:再一段指定时间内,监听用户感兴趣的文件描述符的可读、可写和异常事件。
select系统调用的原型如下:
# include <sys/select.h> int select (int maxfd,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,struct timeval*timeout); /* select 成功时返回就绪(可读、可写和异常)文件描述符的总数。如果在超时间内没有任何文件描述符就绪,select将返回0.select失败返回-1,如果是在select等待期间,程序接收到信号,则select立即返回-1,并设置errno为EINTR。 maxfd 参数指定的被监听的文件描述符的总数。它通常被设置为 select 监听的所 有文件描述符中的最大值+1 readfds、 writefds 和 exceptfds 参数分别指向可读、可写和异常等事件对应的文件 描述符集合。应用程序调用 select 函数时,通过这 3 个参数传入自己感兴趣的文件 描述符。 select 返回时,内核将修改它们来通知应用程序哪些文件描述符已经就绪 通过下列宏可以访问 fd_set 结构中的位: FD_ZERO(fd_set *fdset); // 清除 fdset 的所有位 FD_SET(int fd, fd_set *fdset); // 设置 fdset 的位 fd,fd添加到集合(置一) FD_CLR(int fd, fd_set *fdset); // 清除 fdset 的位 fd int FD_ISSET(int fd, fd_set *fdset);// 测试 fdset 的位 fd 是否被设置 timeout 参数用来设置 select 函数的超时时间。它是一个 timeval 结构类型的指 针,采用指针参数是因为内核将修改它以告诉应用程序 select 等待了多久。 timeval 结构的定义如下 struct timeval {long tv_sec;//秒数long tv_usec://微秒数 }; 如果给 timeout 的两个成员都是 0,则 select 将立即返回。如果 timeout 传递 NULL,则 select 将一直阻塞,直到某个文件描述符就绪 */
1.2select的示例代码
使用select实现的TCP服务器如下:
初始化服务器端的sockfd套接字
int initsocket() {int sockfd=socket(AF_INET,SOCK_STREAM,0);if (sockfd==-1)return -1;struct sockaddr_in saddr;memset(&saddr,0,sizeof (saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof (saddr));if (res==-1)return -1;res=listen(sockfd,5);if (res==-1)return -1;return sockfd; }
初始化记录服务器套接字的数组
void initFds(int fds[],int n) {int i=0;for (;i<n;i++){fds[i]=-1;} }
将套接字描述符添加到数组中
void AddFdToFds(int fds[],int fd,int n) { int i=0;for (;i<n;i++){if (fds[i]==-1){fds[i]=fd;break;}} }
删除数组中的套接字描述符
void DelFromFds(int fds[],int fd,int n) {for (int i=0;i<n;i++){if (fds[i]==fd){fds[i]=-1;break;}} }
将数组中的套接字描述符设置到fd_set变量中,并返回当前最大文件描述符
int SetFsToFdset(fd_set*fdset,int fds[],int n) {FD_ZERO(fdest);//fdest置零int i=0;int maxfd=fds[0];//最大文件描述符的值for (;i<n;i++){if (fds[i]!=-1){FD_SET(fds[i],fdest);//将fdest的位fds[i]的值置为1if (fds[i]>maxfd){maxfd=fds[i];}}}return maxfd; }
服务器和客户端的连接
void GetClientLink(int sockfd,int fds[],int n) { struct sockaddr_in caddr;int len=sizeof (caddr);memset(&caddr,0,sizeof(caddr));int c=accept(sockfd,(struct sockaddr*)&caddr,&len);if (c<0){return;}AddFdToFds(fds,c,n); }
处理客户端数据
void DealClientData(int fds[],int n,int clifd) {char data[128];int num=recv(clifd,data,127,0);if (num<=0){DelFdFromFds(fds,clifd,n);close(clifd);}else{printf ("%d:%s\n",clifd,data);send(clifd,"ok",2,0);} }
处理select返回的就绪事件
void DealReadyEvent(int fds[],int n,fd_set*fdset,int sockfd) {int i=0;for (;i<n;i++){if (fds[i]!=-1&&FD_ISSET(fds[i],fdest)){if(fds[i]==sockfd){GetClientLink(sockfd,fds,n);}else{DealClientLink(fds,n,fds[i]);}}} }
主函数
int main() {int sockfd=initsocket();assert(sockfd!=-1);fd_set readfds;int fds[1024];initFds(fds,1024);AddFdToFds(fds,sockfd,1024);while(1){int maxfd=SetFdToFdset(&readfds,fds,MAX_FD);struct timeval timeout;timeout.tv_sec=2;//秒数timeout.tv_usec=0;//微秒数int n=select(maxfd+1,&readfds,NULL,NULL,&timeout);if (n<0){printf ("select error\n"); break; }else if (n==0){printf ("timeout\n");continue;}DealReadyEvent(fds, 1024, &readfds, sockfd);}exit(0); }
TCP 的客户端代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> int initsocket() {int sockfd=socket(AF_INET,SOCK_STREAM,0);if (sockfd==-1)return -1;struct sockaddr_in saddr;memset(&saddr,0,sizeof (saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof (saddr));if (res==-1)return -1;res=listen(sockfd,5);if (res==-1)return -1;return sockfd; } int main () {int sockfd=initsocket();assert(sockfd!=-1);while(1){printf ("please input:");char buff[128]={0};fgets(buff,127,stdin);if (strncmp(buff,"bye",3)){break;}int n=send(sockfd,buff,strlen(buff)-1,0);if (n<=0){printf ("send error\n");break;}memset(buff,0,128);n=recv(sockfd,buff,127,0);if(n<=0){printf ("recv error\n");break;}printf ("%s\n",buff);}close(sockfd);exit(0); }
相关文章:

Linux I/O复用函数的使用情况和select接口的介绍
I/O 复用使得程序能同时监听多个文件描述符,这对于提高程序的性能至关重要。通常, 网络程序在下列情况下需要使用 I/O 复用技术: 1.TCP服务器同时要处理监听套接字和连接套接字 2.服务器同时要处理TCP请求和UDP请求。 3.程序同时要处理多个套…...
leetcode:数字转换为十六进制数(详解)
前言:内容包括:题目,代码实现,大致思路,代码解读 题目: 给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。 注意: 十六进制中所有字…...
Android 10 设置人脸解锁时,锁屏显示人脸解锁图标
Android 10设置人脸解锁时,锁屏解锁图标不会显示人脸图标,若想显示人脸图标,可参考以下两点进行修改: 1.此处引用人脸图标资源,请参考如下修改: diff --git a/packages/SystemUI/src/com/android/systemui/…...

【嵌入式环境下linux内核及驱动学习笔记-(5-驱动的并发控制机制)】
目录 1、上下文和并发1.1 上下文1.2 共享与临界内核中并发控制机制分为以下几类:并发控制机制的使用场景: 2、 并发控制机制--中断屏蔽3、并发控制机制--原子变量3.1 相关函数原子量类型a.设置原子量的值b.获取原子量的值c.原子变量加减d.原子变量自增自…...

必学宝典 黑马《最新JavaWeb开发教程》上线
对于程序员,所在的行业更迭实属过快,如果是为了找一份好工作,学技术前一定要先了解技术在市场中的需求情况。不然等你学完之后,才发现自己学了已被淘汰、过时的技术,白白浪费了宝贵的学习时间,后悔都来不及…...
【社区图书馆】学习如何读书
人类社会只有发明了发明的方法之后才能发展。同样道理,你们只有学习了学习的方法之后才能进步。 ——查理芒格 进了开发的门,从一开始就在查文档、百度搜 bug 解决的文章、买书,读书。买了很多很厚的工具书,然后拿来垫桌子。再然后…...
CO02工单组件,新增/删除/修改
REPORT zpp153. 事务代码: ZPP153-整散车生产订单自动调整程序名称:ZPP153-整散车生产订单自动调整程序目的:ZPP153-整散车生产订单自动调整开发人员: *(修改日志)--------------------------------------------------------日志号…...
MIT6.824 lab3AB记录
实验目标:基于raft日志复制算法实现的线性一致性kv存储引擎。 线性一致性: 所有的读操作都能够读取到最近一次写操作的结果。所有节点(或者进程)在同一时刻,看到的数据都是相同的。 简而言之,线性一致性…...
一分钟了解美国棒球体系·棒球1号位
美国棒球体系是一个庞大且复杂的体系,涵盖了从青少年到职业的各个层次。下面是美国棒球体系的主要组成部分: 1. 青少年棒球(Youth Baseball) 美国的青少年棒球体系包括各种地区和全国性的联盟,如Little League、Pony…...

通过ObjectMapper和JsonNode 把JSON字符串转换成树结构数据和获取树节点数据
一.简介 今天同事有个需求,要把一个JSON字符串转换成一个树结构的数据并获取节点数据,鉴于自己不想写递归去转换,于是使用ObjectMapper和JsonNode类去实现。 二.依赖 pom文件引入依赖: <dependency><groupId>com.…...

鉴源论坛 · 观模丨面向界面的图形化测试技术
作者 | 熊一衡 华东师范大学软件工程学院博士 苏亭 华东师范大学软件工程学院教授 版块 | 鉴源论坛 观模 01 什么是面向界面的图形化测试(GUI Testing) 图形用户界面(GUI) 是一种通过图形化方式呈现信息、数据、功能和操作的用户界面,旨在…...

Midjourney以图生图的详细教程(含6种案例介绍)
🏆 文章目标:学习并介绍Midjourney以图生图的详细教程 🍀 Midjourney以图生图的详细教程 ✅ 创作者:熊猫Jay 🎉 个人主页:Jay的个人主页 🍁 展望:若本篇讲解内容帮助到您,…...

基于单片机的电路特性测试仪的设计
摘 要 当今社会科技的飞速发展,智能和便捷已经成为人们的日常诉求。现在放大电路在使用过程中经常出现故障,并且需要测试电路数据,但是大多数是手动进行测试,一定程度上影响了工作效率。 为了测量数据更安全更便捷,针…...

五一将迎2亿人次出行,君子签助力旅行社合规高效签旅游电子合同
近日,为规范旅游市场秩序,促进旅行社高质量发展,文旅部发布了《文化和旅游部办公厅关于进一步规范旅游市场秩序的通知》(下称《通知》),对旅游业提出了新的要求。 《通知》中规范了旅行社经营行为。旅行社要…...
IAP升级遇到的问题
文章目录 1. app程序在SystemClock_Config中跑飞2. 程序HAL_Delay中卡死3. 通过外部flash模拟的U盘没能被电脑识别4. 将bin文件拷贝到片内flash中失败5、APP程序跳转过后串口不能工作 这几天在STM32G473使用IAP升级的时候踩了不少坑 1. app程序在SystemClock_Config中跑飞 boo…...
简单聊聊k8s,和docker之间的关系
前言 随着云原生和微服务架构的快速发展,Kubernetes和Docker已经成为了两个重要的技术。但是有小伙伴通常对这两个技术的关系产生疑惑: 既然有了docker,为什么又出来一个k8s? 它俩之间是竞品的关系吗? 傻傻分不清。…...

半小时学会HTML5
一、了解几个概念 1、HTML定义 HTML是(Hyper Text Markup Language)超文本标记语言,超文本包含:文字、图片、音频、视频、动画等。 2、W3C 是什么? W3C 即(World Wide Web Consortium) 万维…...

研报精选230421
目录 【行业230421南京证券】氢能行业:地缘政治加速绿色能源转型 【行业230421华安证券】AIGC行业研究框架与投资逻辑 【行业230421信达证券】工控行业深度报告:行业拐点将至,国产品牌加速崛起 【个股230421国信证券_华阳集团】聚焦汽车智能化…...

AI绘图风格对照表/画风样稿详细研究记录及经验总结(分析Midjourney和Stable Diffusion风格提示词实际使用情况)不断更新中...
Midjourney和Stable Diffusion都可以通过输入文本生成出令人惊叹的AI图像。 Midjourney是一个收费的在线服务,通过discord对话的形式来生图,局限性较大,但由于后台官方模型做得好,因此出图效果非常完美; Stable Diffus…...

人工智能论文的风格特点
搞清楚AI领域论文的风格特点是写出一篇高质量AI论文的前提,AI领域的论文有如下显著特点。 1. 论文的架构非常清晰且富有逻辑。一篇高质量的AI论文,读者通过大致扫一眼论文的各级标题就能够对论文的写作思路形成清晰的认识,明白论文各部分之间…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...

JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
AT模式下的全局锁冲突如何解决?
一、全局锁冲突解决方案 1. 业务层重试机制(推荐方案) Service public class OrderService {GlobalTransactionalRetryable(maxAttempts 3, backoff Backoff(delay 100))public void createOrder(OrderDTO order) {// 库存扣减(自动加全…...