当前位置: 首页 > news >正文

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 复用使得程序能同时监听多个文件描述符&#xff0c;这对于提高程序的性能至关重要。通常&#xff0c; 网络程序在下列情况下需要使用 I/O 复用技术&#xff1a; 1.TCP服务器同时要处理监听套接字和连接套接字 2.服务器同时要处理TCP请求和UDP请求。 3.程序同时要处理多个套…...

leetcode:数字转换为十六进制数(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 给定一个整数&#xff0c;编写一个算法将这个数转换为十六进制数。对于负整数&#xff0c;我们通常使用 补码运算 方法。 注意: 十六进制中所有字…...

Android 10 设置人脸解锁时,锁屏显示人脸解锁图标

Android 10设置人脸解锁时&#xff0c;锁屏解锁图标不会显示人脸图标&#xff0c;若想显示人脸图标&#xff0c;可参考以下两点进行修改&#xff1a; 1.此处引用人脸图标资源&#xff0c;请参考如下修改&#xff1a; diff --git a/packages/SystemUI/src/com/android/systemui/…...

【嵌入式环境下linux内核及驱动学习笔记-(5-驱动的并发控制机制)】

目录 1、上下文和并发1.1 上下文1.2 共享与临界内核中并发控制机制分为以下几类&#xff1a;并发控制机制的使用场景&#xff1a; 2、 并发控制机制--中断屏蔽3、并发控制机制--原子变量3.1 相关函数原子量类型a.设置原子量的值b.获取原子量的值c.原子变量加减d.原子变量自增自…...

必学宝典 黑马《最新JavaWeb开发教程》上线

对于程序员&#xff0c;所在的行业更迭实属过快&#xff0c;如果是为了找一份好工作&#xff0c;学技术前一定要先了解技术在市场中的需求情况。不然等你学完之后&#xff0c;才发现自己学了已被淘汰、过时的技术&#xff0c;白白浪费了宝贵的学习时间&#xff0c;后悔都来不及…...

【社区图书馆】学习如何读书

人类社会只有发明了发明的方法之后才能发展。同样道理&#xff0c;你们只有学习了学习的方法之后才能进步。 ——查理芒格 进了开发的门&#xff0c;从一开始就在查文档、百度搜 bug 解决的文章、买书&#xff0c;读书。买了很多很厚的工具书&#xff0c;然后拿来垫桌子。再然后…...

CO02工单组件,新增/删除/修改

REPORT zpp153. 事务代码&#xff1a; ZPP153-整散车生产订单自动调整程序名称&#xff1a;ZPP153-整散车生产订单自动调整程序目的&#xff1a;ZPP153-整散车生产订单自动调整开发人员&#xff1a; *(修改日志)--------------------------------------------------------日志号…...

MIT6.824 lab3AB记录

实验目标&#xff1a;基于raft日志复制算法实现的线性一致性kv存储引擎。 线性一致性&#xff1a; 所有的读操作都能够读取到最近一次写操作的结果。所有节点&#xff08;或者进程&#xff09;在同一时刻&#xff0c;看到的数据都是相同的。 简而言之&#xff0c;线性一致性…...

一分钟了解美国棒球体系·棒球1号位

美国棒球体系是一个庞大且复杂的体系&#xff0c;涵盖了从青少年到职业的各个层次。下面是美国棒球体系的主要组成部分&#xff1a; 1. 青少年棒球&#xff08;Youth Baseball&#xff09; 美国的青少年棒球体系包括各种地区和全国性的联盟&#xff0c;如Little League、Pony…...

通过ObjectMapper和JsonNode 把JSON字符串转换成树结构数据和获取树节点数据

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

鉴源论坛 · 观模丨面向界面的图形化测试技术

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

Midjourney以图生图的详细教程(含6种案例介绍)

&#x1f3c6; 文章目标&#xff1a;学习并介绍Midjourney以图生图的详细教程 &#x1f340; Midjourney以图生图的详细教程 ✅ 创作者&#xff1a;熊猫Jay &#x1f389; 个人主页&#xff1a;Jay的个人主页 &#x1f341; 展望&#xff1a;若本篇讲解内容帮助到您&#xff0c…...

基于单片机的电路特性测试仪的设计

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

五一将迎2亿人次出行,君子签助力旅行社合规高效签旅游电子合同

近日&#xff0c;为规范旅游市场秩序&#xff0c;促进旅行社高质量发展&#xff0c;文旅部发布了《文化和旅游部办公厅关于进一步规范旅游市场秩序的通知》&#xff08;下称《通知》&#xff09;&#xff0c;对旅游业提出了新的要求。 《通知》中规范了旅行社经营行为。旅行社要…...

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之间的关系

前言 随着云原生和微服务架构的快速发展&#xff0c;Kubernetes和Docker已经成为了两个重要的技术。但是有小伙伴通常对这两个技术的关系产生疑惑&#xff1a; 既然有了docker&#xff0c;为什么又出来一个k8s&#xff1f; 它俩之间是竞品的关系吗&#xff1f; 傻傻分不清。…...

半小时学会HTML5

一、了解几个概念 1、HTML定义 HTML是&#xff08;Hyper Text Markup Language&#xff09;超文本标记语言&#xff0c;超文本包含&#xff1a;文字、图片、音频、视频、动画等。 2、W3C 是什么&#xff1f; W3C 即&#xff08;World Wide Web Consortium&#xff09; 万维…...

研报精选230421

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

AI绘图风格对照表/画风样稿详细研究记录及经验总结(分析Midjourney和Stable Diffusion风格提示词实际使用情况)不断更新中...

Midjourney和Stable Diffusion都可以通过输入文本生成出令人惊叹的AI图像。 Midjourney是一个收费的在线服务&#xff0c;通过discord对话的形式来生图&#xff0c;局限性较大&#xff0c;但由于后台官方模型做得好&#xff0c;因此出图效果非常完美&#xff1b; Stable Diffus…...

人工智能论文的风格特点

搞清楚AI领域论文的风格特点是写出一篇高质量AI论文的前提&#xff0c;AI领域的论文有如下显著特点。 1. 论文的架构非常清晰且富有逻辑。一篇高质量的AI论文&#xff0c;读者通过大致扫一眼论文的各级标题就能够对论文的写作思路形成清晰的认识&#xff0c;明白论文各部分之间…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

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…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

PHP 8.5 即将发布:管道操作符、强力调试

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

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...