【网络编程】IO多路复用


        IO多路复用是一种高效的I/O处理方式,它允许单个进程能够同时监视多个文件描述符(sockets、文件等),并在其中任何一个文件描述符准备好进行I/O操作时进行处理。它的核心在于使用少量的线程或进程来管理多个I/O操作,以提高系统的性能和响应速度

一、概念


1. IO多路复用的核心

        文件描述符集合:使用一个数据结构(如数组或位图)来管理多个文件描述符,通常使用select、poll或epoll等系统调用来监视这些文件描述符。

        阻塞与非阻塞:IO多路复用可以与阻塞和非阻塞I/O一起使用。非阻塞I/O允许程序立即返回,而不必等待数据准备好。

        事件驱动:当一个或多个文件描述符准备好进行读取或写入操作时,IO多路复用会触发相应的事件,从而通知应用程序执行相应的操作。

        单线程/多线程:IO多路复用可以由单个线程或多个线程来处理,取决于应用程序的需求。通常,单个线程可以管理多个文件描述符。

2. 四种IO模型

阻塞IO模型(Blocking IO)

        ① 阻塞IO模型是最简单的IO模型之一;
        ② 当程序执行IO操作时,它会被阻塞,直到IO操作完成为止;
        ③ 这种模型的效率较低,因为程序在等待IO完成期间无法执行其他任务。


非阻塞IO模型(Non-blocking IO)

        ① 非阻塞IO模型允许程序在等待IO完成时继续执行其他任务;
        ② 当程序请求IO操作时,它会立即返回,不会被阻塞;
        ③ 程序需要不断轮询以检查IO操作是否完成,这可能会导致CPU资源浪费。


多路复用IO模型(IO Multiplexing)

        ① 多路复用IO模型使用了一种机制,允许程序同时等待多个IO操作的完成;
        ② 通常使用select、poll或epoll等系统调用来实现;
        ③ 程序可以同时监视多个文件描述符,只有当其中某个文件描述符有IO事件发生时,程序才会被唤醒处理该事件。


异步IO模型(Asynchronous IO)

        ① 异步IO模型中,程序发起IO操作后立即返回,不会阻塞;
        ② 当IO操作完成时,系统会通知程序,然后程序处理完成的数据;
        ③ 这种模型的效率很高,因为程序不需要轮询,但实现复杂度较高。

        因此IO复用的核心基本思想为:先构造一张有关描述符的表,然后调用一个函数。当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。函数返回时告诉进程哪些描述符已就绪,可以进行I/O操作。

3. IO复用的优点

  • 高效利用CPU:相较于传统的多线程/多进程模型,IO多路复用可以减少线程/进程的创建和切换开销,提高CPU的利用率。

  • 减少资源占用:减少了每个连接的资源消耗,因为不再需要为每个连接创建一个线程或进程。

  • 简化程序逻辑:IO多路复用可以简化程序的逻辑,使得代码更易于维护和理解。

二、代码实现(TCP服务器端为例)

1. 创建监听套接字socket

	// 创建套接字socketint ser_socket = socket(AF_INET, SOCK_STREAM, 0);if (ser_socket == -1){perror("socket");return -1;}int reuse = 1;//设置套接字属性,  SO_REUSEADDR 允许端口重用 if(setsockopt(ser_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse))<0){perror("setsockopt error");return -1;}


2. 初始化套接字和服务器自己的IP地址结构体(包括端口号)

// 初始化地址结构体 // IP地址+PORT端口号struct sockaddr_in addr;addr.sin_family = AF_INET;   						//地址簇addr.sin_port = atoi(argv[1]);								//端口(一般以传参的传进来)// addr.sin_addr.s_addr = inet_addr("192.168.1.25");	//IP地址addr.sin_addr.s_addr = htonl(INADDR_ANY);			//用特殊的"0.0.0.0"这个IP来绑定本机IP地址


3. 绑定bind

// 绑定地址结构体bindint b = bind(ser_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));if(b == -1){perror("bind");return -1;}printf("绑定成功\n");


4. 开启监听listen

int l = listen(ser_socket, 3);if (l == -1){perror("listen");return -1;}printf("监听成功\n");//ser_socket由 待链接套接字 变成 监听套接字


5. 创建文件描述符集合,并初始化

        这里呢设置了套接字超时,就是在规定的时间内如果没有客户端连接,则退出服务器。

//设置套接字接收超时struct timeval tv;tv.tv_sec = 5; //超时秒数tv.tv_usec = 0;setsockopt(ser_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); // 等待连接acceptstruct sockaddr_in c_addr;		//用来存放客户端链接成功之后的IP加端口int addrlen = sizeof(c_addr);int new_socekt = accept(ser_socket, (struct sockaddr *)&c_addr, &addrlen);if (new_socekt == -1){printf("延时时间到了,服务器退出了\n");perror("accept");return -1;}// new_socekt 链接成功之后,用来通信的套接字printf("客户端【%s】【%u】连接成功\n", inet_ntoa(c_addr.sin_addr), c_addr.sin_port);//客户端的IP跟端口,IP是你客户端本身自带的,但是端口是系统随机分配的啊// 接收消息read/recvchar buf[1024];while(1){bzero(buf, sizeof(buf));read(new_socekt, buf, sizeof(buf));// recv(new_socekt, buf, sizeof(buf), 0);printf(" client %s\n", buf);}


6. 资源释放,关闭套接字

close(new_socekt);// shutdown(new_socekt, SHUT_RDWR);

三、使用场景


       1. 网络服务器: IO复用常用于网络服务器,特别是需要同时处理大量客户端连接的情况,例如Web服务器、聊天服务器和在线游戏服务器。

       2. 网络代理: 代理服务器需要同时监听多个客户端和服务器连接,以便在它们之间传递数据,这是IO复用的典型应用场景。

        3. 聊天应用: 实时聊天应用通常需要处理多个客户端的消息,IO复用可以用于同时监视多个客户端连接,以便实时传递消息。

        4. 文件传输应用: 文件传输服务器需要同时处理多个文件上传或下载请求,使用IO复用可以有效管理这些请求。

        更多C/C++语言、Linux系统、数据结构和ARM板实战相关文章,关注专栏:

   手撕C语言

            玩转linux

                    脚踢数据结构

                            系统、网络编程

                                     探索C++

                                             6818(ARM)开发板实战

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉🎉🎉感谢关注🎉🎉🎉

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

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

相关文章

RK3568平台开发系列讲解(音视频篇)H264 的编码结构

🚀返回专栏总目录 文章目录 一、H264 的编码结构1.1、帧类型1.2、GOP1.3、Slice沉淀、分享、成长,让自己和他人都能有所收获!😄 📢视频编码的码流结构其实就是指视频经过编码之后得到的二进制数据是怎么组织的,换句话说,就是编码后的码流我们怎么将一帧帧编码后的图像…

通过rabbitmq生成延时消息,并生成rabbitmq镜像

通过rabbitmq生成延时消息队列&#xff0c;并生成rabbitmq镜像 整体描述1. 使用场景2. 目前问题3. 前期准备 具体步骤1. 拉取镜像2. 运行镜像3. 安装插件4. 代码支持4.1 config文件4.2 消费监听4.2 消息生产 5. 功能测试 镜像操作1. 镜像制作2. 镜像导入 总结 整体描述 1. 使用…

蠕虫病毒流量分析案例

背景 某供排水集团的网络管理员对其网络的健康状况持认可态度&#xff0c;表示网络运行正常&#xff0c;没有发现异常行为。然而&#xff0c;由于网络环境变得越来越复杂&#xff0c;仅凭借传统的网络经验已经不能全面了解网络情况。因此&#xff0c;我们为供排水集团安装了Ne…

Golang复习

golang的特点 Golang 针对并发进行了优化&#xff0c;并且在规模上运行良好 自动垃圾收集明显比 Java 或 Python 更有效&#xff0c;因为它与程序同时执行 golang数据类型 基本数据类型&#xff08;值类型&#xff09; 布尔类型 数字类型 整型 根据有符号分为&#xff1a;…

[NLP]LLM---FineTune自己的Llama2模型

一 数据集准备 Let’s talk a bit about the parameters we can tune here. First, we want to load a llama-2-7b-hf model and train it on the mlabonne/guanaco-llama2-1k (1,000 samples), which will produce our fine-tuned model llama-2-7b-miniguanaco. If you’re …

华为云API对话机器人CBS的魅力—实现简单的对话操作

云服务、API、SDK&#xff0c;调试&#xff0c;查看&#xff0c;我都行 阅读短文您可以学习到&#xff1a;人工智能AI智能的问答管理、全面的对话管理、高效训练部署 1.IntelliJ IDEA 之API插件介绍 API插件支持 VS Code IDE、IntelliJ IDEA等平台、以及华为云自研 CodeArts …

每日刷题-3

目录 一、选择题 二、编程题 1、计算糖果 2、进制转换 一、选择题 1、 解析&#xff1a;在C语言中&#xff0c;以0开头的整数常量是八进制的&#xff0c;而不是十进制的。所以&#xff0c;0123的八进制表示相当于83的十进制表示&#xff0c;而123的十进制表示不变。printf函数…

ASP.NET Core IOC容器

//IOC容器支持依赖注入{ServiceCollection serviceDescriptors new ServiceCollection();serviceDescriptors.AddTransient<IMicrophone, Microphone>();serviceDescriptors.AddTransient<IPower, Power>();serviceDescriptors.AddTransient<IHeadphone, Headp…

【SQL应知应会】索引 • Oracle版:B-树索引;位图索引;函数索引;单列与复合索引;分区索引

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文免费学习,自发文起3天后,会收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 索引 • MySQL版 前言一、Oracle索引1.索引概述及分类…

upload-labs1-17思路

1 直接写一个php文件测试一下&#xff0c;发现弹窗不让上传 原理很简单&#xff0c;就是把后缀名拿出来过滤一遍&#xff0c;而白名单就是弹窗的这三个 解决方法&#xff1a; 因为这是在前端防御的一个手段&#xff0c;所以直接在浏览器设置上禁用js就行了&#xff1a; 也可…

微服务-OpenFeign基本使用

一、前言 二、OpenFeign基本使用 1、OpenFeign简介 OpenFeign是一种声明式、模板化的HTTP客户端&#xff0c;它使得调用RESTful网络服务变得简单。在Spring Cloud中使用OpenFeign&#xff0c;可以做到像调用本地方法一样使用HTTP请求访问远程服务&#xff0c;开发者无需关注…

stm32 学习笔记:GPIO输出

一、GPIO简介 引脚电平 0-3.3V,部分可容忍5V&#xff0c;对输出而言最大只能输出3.3V, 只要可以用高低电平来控制的地方&#xff0c;都可以用GPIO来完成&#xff0c;如果控制的功率比较大的设备&#xff0c;只需加入驱动电路即可 GPIO 通用输入输出口&#xff0c;可配置为 8种 …

2023国赛数学建模E题思路代码 - 黄河水沙监测数据分析

# 1 赛题 E 题 黄河水沙监测数据分析 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变 化和人民生活的影响&#xff0c; 以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾 等方面都具有重要的理论指导意义。 附件 1 给出了位…

【实训】“宅急送”订餐管理系统(程序设计综合能力实训)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 大一小学期&#xff0c;我迎来了人生中的第一次实训…

2023/9/8 -- C++/QT

作业 1> 自行封装一个栈的类&#xff0c;包含私有成员属性&#xff1a;栈的数组、记录栈顶的变量 成员函数完成&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小 02stack.h: #ifndef __02STACK_H__ #define __…

无涯教程-JavaScript - IMSIN函数

描述 IMSIN函数以x yi或x yj文本格式返回复数的正弦。复数的正弦为- $$\sin(x yi) \sin(x)\cosh(y) \cos(x)\sin(y)i $$ 语法 IMSIN (inumber)争论 Argument描述Required/OptionalInumberA Complex Number for which you want the sine.Required Notes Excel中的复数仅…

活动预告 | 龙智、紫龙游戏与JFrog专家将出席龙智DevSecOps研讨会,探讨企业大规模开发创新

2023年9月8日&#xff08;周五&#xff09;下午13:30-19:45&#xff0c;龙智即将携手Atlassian与JFrog在上海共同举办主题为“大规模开发创新&#xff1a;如何提升企业级开发效率与质量”的线下研讨会。 在此次研讨会上&#xff0c;龙智高级咨询顾问、Atlassian认证专家叶燕秀…

【List篇】使用Arrays.asList生成的List集合,操作add方法报错

早上到公司&#xff0c;刚到工位&#xff0c;测试同事就跑来说"功能不行了&#xff0c;报服务器异常了&#xff0c;咋回事";我一脸蒙&#xff0c;早饭都顾不上吃&#xff0c;要来了测试账号复现了一下&#xff0c;然后仔细观察测试服务器日志&#xff0c;发现报了一个…

K8S 基础概念学习

1.K8S 通过Deployment 实现滚动发布&#xff0c;比如左边的ReplicatSet 的 pod 中 是V1版本的镜像&#xff0c;Deployment通过 再启动一个 ReplicatSet 中启动 pod中 镜像就是V2 2.每个pod 中都有一个pause 容器&#xff0c;他会连接本pod中的其他容器&#xff0c;实现互通。p…

【计算机网络】HTTP(上)

文章目录 1.HTTP概念2. URLurlencode 和 urldecode转义规则 3. HTTP的宏观理解HTTP的请求HTTP的响应 4. 见一见HTTP请求和响应请求报头 1. 模拟一个简单的响应response响应报头 2. 从路径中获取内容ReadFile函数的实现 3.不同资源进行区分反序列化的实现ReadOneLine函数的实现P…