Linux多路IO复用:select

news2024/9/25 1:18:39

1. 多路IO复用

内核监听多个socket文件描述符读写缓冲区属性的变化,若某个文件描述符的读缓冲区有变化,则将该事件告诉应用层。

内核提供多路IO复用的API:select、poll(使用较少)、epoll。


2. select

select原理

用户态创建文件描述符位图,将需要被监听的文件描述符置1,同时拷贝一份文件描述符位图做备份;

每调用一次select就将该文件描述符位图拷贝给内核,内核监听文件描述符是否有事件,将有事件的文件描述符保留,其余文件描述符置0,然后拷贝给用户态;

用户态遍历内核拷贝过来的文件描述符位图,若lfd(监听文件描述符)有事件则表示有新连接到来,则将新连接的文件描述符加入到备份的文件描述符位图中;

若其他文件描述符有事件,则进行处理;若有客户端关闭,则从备份文件描述符中删除该客户端的文件描述符;

下次再监听时则将备份的文件描述符位图拷贝到内核态进行监听。

select优缺点

优点:

        ① 是POSIX标准,跨平台较好:Linux、Windows、MAC OS;

缺点:

        ① 文件描述符数最大限制为1024,;可修改,但需要重新编译内核;

        ② 仅返回有变化的文件描述符个数,需要自己遍历才知道是哪个文件描述符发生变化;

        ③ 文件描述符位图需要在用户空间和内核空间来回拷贝;

        ④ 客户端较多,但只有少量客户端活跃时,效率低,因为每次都遍历所有的客户端。

select API

#include<sys/select.h>
#include<sys/types.h>

int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
/*
功能:
    监听多个文件描述符的属性(读、写、异常)变化。
参数:
    nfds:最大文件描述符+1
    readfds:需要监听的读文件描述符的集合
    writefds:需要监听的写文件描述符的集合,通常为NULL
    exceptfds:需要监听的异常文件描述符的集合,通常为NULL
    timeout:
            > 0:监听超时时间(多久监听一次);
            0:无文件描述符变化则立即返回;
            NULL:阻塞监听到有文件描述符变化才返回。
返回值:
    > 0:变化的文件描述符的个数;
    = 0:没有文件描述符发生变化;
    < 0 :调用发生错误,会设置errno。
*/

struct timeval {
    long tv_sec;  // 秒
    long tv_usec; // 微秒
}

void FD_CLR(int fd, fd_set* set);  // 从文件描述符位图set中移除文件描述符fd
int FD_ISSET(int fd, fd_set* set); // 判断文件描述符fd是否在文件描述符位图set中
void FD_SET(int fd, fd_set* set);  // 将文件描述符fd添加到文件描述符位图set中
void FD_ZERO(fd_set* set);         // 清空文件描述符位图set

select示例:

#include<stdio.h>
#include<sys/select.h>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include"wrap.h"

#define PORT 8888

int main(int argc, const char* argv[]) {

    // 1.创建socket,bind
    int lfd = tcp4bind(PORT, NULL);

    // 2.监听
    Listen(lfd, 128);

    // 3.while select监听
    int maxfd = lfd; // 最初监听到最大的文件描述符
    fd_set oldset, rset;
    FD_ZERO(&oldset); // 清空集合
    FD_ZERO(&rset);   // 清空集合
    FD_SET(lfd, &oldset);  // 将lfd加入oldset
    while (1) {

        rset = oldset; // 备份oldset
        int n = select(maxfd + 1, &rset, NULL, NULL, 0); // select监听
        if (n < 0) {
            perror("select");
            break;
        } else if (0 == n) {
            continue; // 无文件描述符变化则继续监听
        } else { // 有文件描述符发生变化

            if (FD_ISSET(lfd, &rset)) { // lfd有变化, 表示有新连接到来
                struct sockaddr_in cliaddr;
                socklen_t len = sizeof(cliaddr);
                char ip[16] = "";

                // 提取新连接
                int cfd = Accept(lfd, (struct sockaddr*)&cliaddr, &len);

                printf("新连接到来:IP = %s, port = %d\n",
                    inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, ip, 16),
                    ntohs(cliaddr.sin_port));
                FD_SET(cfd, &oldset); // 将cfd加入到oldset中
                if (cfd > maxfd) { // 更新maxfd
                    maxfd = cfd;
                }
                if (--n == 0) { // 如果只有lfd有变化,则继续下一轮监听
                    continue;
                }
            }

            // cfd有变化,遍历lfd之后的文件描述符是否有变化
            for (int i = lfd + 1; i <= maxfd; i++) {
                if (FD_ISSET(i, &rset)) { // 若文件描述符i有变化
                    char buf[1500] = ""; // 1500是以太网最大传输单元
                    int ret = Read(i, buf, 1500);
                    if (ret < 0) { // 出错
                        perror("read");
                        close(i);  // 关闭文件描述符
                        FD_CLR(i, &oldset);  // 从oldset中删除该文件描述符
                    } else if (0 == ret) {
                        printf("客户端关闭\n");
                        close(i);  // 关闭文件描述符
                        FD_CLR(i, &oldset);  // 从oldset中删除该文件描述符
                    } else {
                        printf("客户端:%s\n", buf);
                        write(i, buf, ret);
                    }
                }
            }
        }
    }
    return 0;
}

运行结果:

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

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

相关文章

设置让Windows每天在指定时间自动关机

其实我们的电脑是可以设置每天在指定的时间点自动关机的&#xff0c;具体操作方法&#xff1a; 1、开打电脑&#xff0c;点击电脑系统左下角windows图标&#xff0c;选择“控制面板”并进入&#xff1b;如图 2、在控制面板界面找到“管理工具”&#xff0c;点击开打&#xff1b…

idea2021.3.x激活教程

第一步: 下载最新的 IDEA 2021.3.3 版本安装包 先从 IDEA 官网下载 IDEA 2021.3.3 版本的安装包&#xff0c;下载链接可以自行百度IDEA官网。 点击下载&#xff0c;耐心等待下载完成。 第二步: 开始安装(已安装可跳过此步骤) 指定安装目录。 勾选创建桌面快捷方式&#xff0…

springboot+java共享厨房租赁信息系统

功能介绍开发环境 springboot是基于spring的快速开发框架, 相比于原生的spring而言, 它通过大量的java config来避免了大量的xml文件, 只需要简单的生成器便能生成一个可以运行的javaweb项目, 是目前最火热的java开发框架 开发语言&#xff1a;Java 框架&#xff1a;springb…

浪潮盒子IPBS9505-多遥控版-S905L/M2芯片-安卓4.4.2-线刷固件包

浪潮盒子IPBS9505-多遥控版-S905L&#xff0f;M2芯片-安卓4.4.2-线刷固件包-内有教程和短接点-当贝纯净桌面。 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&…

微机原理 || 第六章 I/O接口 测试题(答案+解析)

1、下列设备与CPU相连不需要通过接口的是()。 A内存条 B键盘 C U盘. D 硬盘 2、I/O接口电路通常具有()三种端口。 A 数据端口、控制端口、状态端口 (信息分类) 3、以下叙述中&#xff0c;不属于接口功能的是()。 A 提供接口的状态&#xff0c;以便CPU查询 B实现数据格式…

基于vue的毕业生研究生大学生交流学习平台

下面进行系统的功能需求分析。 1.前台功能模块&#xff1a;可以在前台Web浏览器中查看这些功能。 用户注册模块&#xff1a;将用户信息记录到用户表。 用户登录模块&#xff1a;用来区分三种用户&#xff0c;普通用户、普通管理员和超级管理员。 个人信息管理&#xff1a;用户登…

【Linux】Linux安装Maven(图文解说详细版)

文章目录 前言1.去官网下载2.下载完成上传到/opt目录下3.解压缩4.配置环境变量5.刷新配置文件使得配置文件生效6.然后我们运行mvn -v查看是否成功7.出现错误&#xff0c;接下来全程高能带你刨析这个错误&#xff01;8.这里又出现一个坑&#xff0c;就是每次重新进终端的时候mvn…

学习笔记——new关键字在底层究竟做了什么

new关键字&#xff08;操作符&#xff09;在底层究竟做了什么&#xff1f; 一、概念理解 函数调用之前带有关键字new&#xff0c;它就构成了构造函数调用。 与普通函数调用在实参处理、调用上下文、返回值方面不同。 一&#xff09;实参处理 相同点&#xff1a;如果有实参&…

【无标题】每天一道算法练习题--Day24 第一章 --算法专题 --- ----------平衡二叉树专题

力扣关于平衡二叉树的题目还是有一些的&#xff0c;并且都非常经典&#xff0c;推荐大家练习。今天给大家精选了 4 道题&#xff0c;如果你彻底搞明白了这几道题&#xff0c;碰到其他的平衡二叉树的题目应该不至于没有思路。当你领会了我的思路之后&#xff0c; 建议再找几个题…

一文搞懂linux的proc文件

目录 proc文件夹是干嘛用&#xff1f; proc下都有什么系统信息? /proc/bus /proc/buddyinfo /proc/cgroups /proc/cmdline /proc/consoles /proc/cpuinfo /proc/crypto /proc/devices /proc/diskstats /proc/execdomains /proc/fb /proc/filesystems …

JVM 体系结构

JVM: 跨平台语言 需要不同语言由自己编译器&#xff0c;生成符合 JSR-292 JVM规范的字节码文件&#xff0c;即可在 Java 虚拟机中运行 多语言混合编程: Java 平台上的多语言混合编程正成为主流&#xff0c;通过特定领域的语言去解决特定领域的问题是当前软件开发应对日趋复杂…

服务攻防-数据库安全-InfluxdbH2databaseCouchDBElasticSearch数据库漏洞复现

目录 一、Influxdb-未授权访问-Jwt 验证不当 1、Infuxdb简介 2、安全问题 3、漏洞复现 二、H2database-未授权访问-配置不当 1、H2database简介 2、安全问题 3、漏洞复现 三、CouchDB-权限绕过配合RCE-漏洞 1、CouchDB简介 2、安全问题 3、漏洞复现 四 、Elast…

《程序员面试金典(第6版)》面试题 16.15. 珠玑妙算

题目描述 珠玑妙算游戏&#xff08;the game of master mind&#xff09;的玩法如下。 计算机有4个槽&#xff0c;每个槽放一个球&#xff0c;颜色可能是红色&#xff08;R&#xff09;、黄色&#xff08;Y&#xff09;、绿色&#xff08;G&#xff09;或蓝色&#xff08;B&…

为什么我选择订阅ChatGPT Plus计划?

自从ChatGPT诞生以来&#xff0c;它的强大功能和表现一直备受好评。作为一个长期使用者&#xff0c;我一直对其性能和智能感到惊叹。最近&#xff0c;我决定升级我的用户体验&#xff0c;订阅了ChatGPT Plus计划。在这篇博客中&#xff0c;我将向您详细介绍ChatGPT Plus的优势和…

c语言那些有趣的事 -- 猜数字游戏

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章用循环去写一些题目。 让我们开启c语言…

细谈抽象类

目录 抽象类 1.抽象类是被abstract修饰的类 2.抽象类中的抽象方法 3.抽象类中可以有和普通类一样的成员变量和成员方法 4.抽象类不能被实例化 5.那么抽象类不能被实例化要它有何用&#xff1f;&#xff1f;&#xff1f; 6.注意&#xff1a; 抽象类 如果一个类中没有包含足…

基于Open3D的点云处理4-旋转、平移、缩放

三维变换主要包括&#xff1a;平移、旋转、缩放 在open3d中&#xff0c;针对三维对象的变换主要有translate、rotate、scale和transform • Translate 平移 • Rotate 旋转 • Scale 缩放 • Transform 变换矩阵&#xff08;4*4&#xff09; mesh_tx mesh.translate((1.5, …

昆山杜克大学首届毕业生就业情况

昆山杜克大学本科教育以通识博雅课程和跨学科教育为主要特色&#xff0c;倡导文理兼修&#xff0c;并以研究为导向。所有学生入学时不分专业&#xff0c;他们充分地自由选课探索之后&#xff0c;于大二结束之前选择最适合自己的专业。首届毕业生分布于以下12个专业。 教育理念是…

《SQLi-Labs》03. Less 11~15

sqli Less-11知识点题解 Less-12题解 Less-13题解 Less-14题解 Less-15知识点题解 sqli。开启新坑。 Less-11 知识点 第十一关页面发生了变化&#xff0c;是账户登录页面。那么注入点在输入框。 前十关使用的是 get 请求&#xff0c;参数都体现在 url 上&#xff0c;而十一关…

测试2:基础

目录 1.软件测试的生命周期 2.描述BUG 3.定义bug的级别 1.Blocker(崩溃) 2.Critical(严重) 3、Major&#xff08;一般&#xff09;&#xff1a; 4、Minor&#xff08;次要&#xff09;&#xff1a; 4.BUG的生命周期 1.软件测试的生命周期 需求分析,测试计划,测试设计,测…