【Linux网络-多路转接select】
代码:https://gitee.com/nanyi-c/linux/tree/master/day50
一、I/O多路转接之select
1.初始select
系统提供select函数来实现多路复用输入/输出模型
- select系统调用是用来让我们的程序监视多个文件描述符的状态变化的
- 程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变
2.select函数原型
select 是一个在 Unix 和类 Unix 操作系统中的系统调用,用于监控多个文件描述符,等待其中一个或多个文件描述符变得“就绪”。就绪可以意味着可读、可写或者发生异常

参数说明
| 参数 | 描述 |
|---|---|
| nfds | 这是你监控的文件描述符集(readfds、writefds、exceptfds)中最高文件描述符的编号加1。简单来说,它是监控的文件描述符范围的上限 |
| readfds | 输入输出型参数,只关心读事件 |
| writefds | 输入输出型参数,只关心写事件 |
| exceptfds | 输入输出型参数,只关心异常事件 |
| timeout | 输入输出型参数,设置为 NULL,select 将无限期阻塞,直到至少有一个文件描述符就绪。如果 timeout 设置为非 NULL 值,它将在指定的秒数和微秒数后超时 |

以下是 timeval 结构体的定义:
timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则发生函数返回,返回值为0
struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */
};
select 调用的返回值和含义如下:
- 返回值大于0:表示就绪的文件描述符数量。输入输出型参数
- 返回0:表示超时发生,没有文件描述符就绪。
- 返回-1:表示出错,并且设置
errno来指示错误类型。
错误值可能为:
-
EBADF 文件描述词为无效的或该文件已关闭
-
EINTR 此调用被信号所中断
-
EINVAL 参数n为负值
-
ENOMEM 核心内存不足
常见的程序片段如下:
fs_set readset;
FD_SET (fd, &readset);
select(fd+1, &readset, NULL, NULL, NULL) ;
if(FD_ISSET (fd, readse) ([....}
1.select要正常工作,需要借助一个辅助数组,来保存所有合法fd
2.每次使用都要重置
3.就绪了,循环检测处理所有事件
关于fd_set结构
在Linux系统中,fd_set 是一个数据结构,用于表示一组文件描述符的集合。它通常与 select 系统调用一起使用,以便同时监控多个文件描述符的状态(是否可读、可写或有异常发生)。
fd_set 是一个固定大小的位掩码,其中每一位代表一个文件描述符。在内部,它通常是一个长整型数组,数组中的每个元素代表一定范围内的文件描述符。由于 fd_set 的大小是固定的,所以它有一个最大文件描述符的限制,这个限制在 Linux 系统中通常是 FD_SETSIZE(通常定义为 1024)。

常见宏操作
FD_ZERO(fd_set *set):将fd_set清零,即初始化fd_set,使其不包含任何文件描述符。FD_SET(int fd, fd_set *set):将指定的文件描述符fd添加到fd_set集合中。FD_CLR(int fd, fd_set *set):从fd_set集合中移除指定的文件描述符fd。FD_ISSET(int fd, fd_set *set):检查指定的文件描述符fd是否在fd_set集合中。这个宏在select调用后使用,以确定哪些文件描述符已经就绪。
3.理解select执行过程
理解 select 模型的关键在于理解 fd_set,为说明方便,取 fd_set 长度为 1 字节,fd_set 中的每一 bit 可以对应一个文件描述符 fd,则 1 字节长的 fd_set 最大可以对应 8 个 fd。
- 执行 fd_set set; FD_ZERO(&set); 则 set 用位表示是 0000,0000。
- 若 fd=5,执行 FD_SET(fd,&set); 后 set 变为 0001,0000(第 5 位置为 1)。
- 若再加入 fd=2,fd=1,则 set 变为 0001,0011。
- 执行 select(6,&set,0,0,0) 阻塞等待。
- 若 fd=1,fd=2 上都发生可读事件,则 select 返回,此时 set 变为 0000,0011
注意 :没有事件发生的 fd=5 被清空。
4.socket就绪条件
读就绪
- socket 内核中,接收缓冲区中的字节数,大于等于低水位标记 SO_RCVLOWAT,此时可以无阻塞的读取该文件描述符,并且返回值大于 0。
- socket TCP 通信中,对端关闭连接,此时对该 socket 读,则返回 0。
- 监听 socket 上有新的连接请求。
- socket 上有未处理的错误。
写就绪
- socket 内核中,发送缓冲区中的可用字节数(发送缓冲区的空闲位置大小),大于等于低水位标记 SO_SNDLOWAT,此时可以无阻塞的写,并且返回值大于 0。
- socket 的写操作被关闭(close 或者 shutdown),如果此时进行写操作的话,会触发 SIGPIPE 信号。
- socket 使用非阻塞 connect 连接成功或失败之后,socket 上有未读取的错误。
异常就绪
- socket上收到带外数据,关于带外数据,和TCP紧急模式相关(回忆TCP协议头中,有一个紧急指针的字段)
二、SelectServer.hpp
1.基础框架

2.设计Loop

测试
每隔3s轮询一次

如果设置为nullptr,那么就永久阻塞式等待,直到有新链接

无论哪种方式我们建立链接时,服务器会疯狂输出,这是因为我们还没有对收到新链接后怎么做
如果事件就绪,但是不处理,select会一直通知我,直到我处理了

我们重新设置一下

此时便不会疯狂输出,还会显示剩余时间

时间就绪后就可以处理事件了,在rfds内
因为rfds是输入输出型参数,这里已经返回了哪些事已经就绪的

处理事件
首先我们要判断我们的文件描述符是不是就绪的,如果是,就可以建立连接了

测试

已经获得了一个新的sockfd
接下来我们可以读取吗?绝对不能读!读取的时候,条件不一定满足(建立连接–》不发请求,(底层没有数据)读的时候被阻塞,单进程绝对挂掉)
谁最清楚底层fd的数据是否就绪了呢??通过select!
想办法把新的fd添加给select,由select统一进行监管。
select 为什么等待的fd会越来越多??
只要将新的fd,添加到fd_array中即可
初始化数组,并且把0号位给listen套接字

重新设计Loop,并且找到最大的文件fd,使用for循环可以处理多个文件描述符,进行动态更新和确定最大文件描述符

添加一个debug函数便于我们调试以及查看信息

HandlerEvent函数负责检测哪些文件描述符就绪,并根据它们是监听套接字还是普通套接字来调用相应的处理函数。
处理新链接,并把新链接的fd添加到fd_array中

处理普通fd就绪 进行IO

测试

三、select总结
小结:
- select要正常工作,需要借助一个辅助数组,来保存所有合法fd
- 每次使用都要重置
- 就绪了,循环检测处理所有事件
缺点
- 每次调用 select,都需手动设置 fd 集合,从接口使用角度来说也非常不便。
- 每次调用 select,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大。
- 同时每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大。
- select 可监控的文件描述符数量太少。
相关文章:
【Linux网络-多路转接select】
代码:https://gitee.com/nanyi-c/linux/tree/master/day50 一、I/O多路转接之select 1.初始select 系统提供select函数来实现多路复用输入/输出模型 select系统调用是用来让我们的程序监视多个文件描述符的状态变化的程序会停在select这里等待,直到被…...
cmd命令查看电脑的CPU、内存、存储量
目录 获取计算机硬件的相关信息的命令分别的功能结果展示结果说明获取计算机硬件的相关信息的命令 wmic cpu get name wmic memorychip get capacity wmic diskdrive get model,size,mediaType分别的功能 获取计算机中央处理器(CPU)的名称 获取计算机内存(RAM)芯片的容量…...
LVS的 NAT 模式实现 3 台RS的轮询访问
使用LVS的 NAT 模式实现 3 台RS的轮询访问 1.配置 RS(NAT模式)2. 配置 LVS 主机(仅主机、NAT模式)2.1 配置仅主机网卡(192.168.66.150/24 VIP )2.2 配置 NAT 网卡(192.168.88.6/24 DIPÿ…...
phpcms版AI自动发文插件,自动创作,自动配图,自动发布,支持多种大模型
phpcms版本的AI自动发文插件1.0.0版,支持自动写文章,自动配图,自动发布。目前支持DeepSeek,豆包,通义千问,文心一言,讯飞星火,KIMI,腾讯混元登大模型AI。同时有自定义字段…...
C语言判断闰年相关问题
一、简单闰年问题引入 写一个判断年份是否为闰年的程序? 运行结果: 二、闰年问题进阶 使用switch语句根据用户输入的年份和月份,判断该月份有多少天? 第一种写法(判断年份写在switch的case的里面): 运行结果: 第二种解法(先判断闰年): 运行结果: 三、补充 switch中的ca…...
团体协作项目总结Git
使用Git开放时候发现本地, 有些代码并没有被拉取到本地仓库, 又不想再commit一次, 这时候我就想到了 git commit --amend 合并提交 git commit --amend 修改git提交记录用法详解 可以将本次提交记录合并到上一次合并提交 git commit --amendgit rebase -i master^^ // 假设我…...
solana/web3.js 2.0:Solana 转账全流程解析
Solana 区块链以高吞吐量和低交易成本,已成为开发者的热门选择。而 solana /web3.js 2.0 作为最新一代 JavaScript 库,为与 Solana 网络交互提供了更高效、模块化的工具。本文将深入剖析如何使用 solana /web3.js 2.0 实现 Solana 区块链上的转账操作&am…...
数模转换电路(D/A转换器)
将数字信号转换成模拟信号称为数/模转换, 简称D/A(Digital to Analog)转换,实现 D/A 转换的器件称为D/A转换器,简称 DAC(Digital-Analog Converter)。 将模拟信号转换成数字信号称为模/数转换, 简称A/D&a…...
网络基础-路由器和交换机工作配置
三、路由器和交换机的工作原理配置以及华为体系下的小型网络的搭建 3.1路由基础 3.1.1数据转发 通过链路层交换机和网络层路由器进行数据转发 交换机(链路层)mac地址表的数据转发路由器(网络层) ip路由表的数据转发 隔离广播域…...
uv包简单使用案例
uv由Charlie Marsh开发,是Astral Tool的一个快速Python包安装器和解析器。它类似于pip和pip-tools,但速度更快。此外,uv还支持虚拟环境管理,替代venv和virtualenv。 参考:https://github.com/astral-sh/uv 安装&#x…...
PHP接口开发:从基础到高级的全面指南
一、接口基础与核心概念(约800字) 1.1 接口的本质定义 在PHP中,接口(Interface)是一种特殊的抽象结构,它通过interface关键字定义一组方法的契约规范,不包含具体实现。这种设计强制实现类必须遵循统一的调用标准,如: interface PaymentGateway {public function proc…...
JAVA学习*String类
String类 基本知识 String类的构造方法 String类的构造方法有很多,我们需要掌握常见的构造方法,来赋初识值。 1、new一个String类的对象 String name new String("张三");2、使用字符串常量进行赋值 String name "张三";相当…...
Java IO框架体系深度解析:从四基类到设计模式实践
Java IO框架体系深度解析:从四基类到设计模式实践 一、IO流体系架构总览 1.1 四基类设计哲学 Java IO框架以InputStream、OutputStream、Reader、Writer四个抽象类为根基,构建了完整的流式IO体系。这种设计体现了以下核心原则: 抽象分层&a…...
【读书笔记】华为《从偶然到必然》
note 华为的成功并非偶然,而是通过IPD体系、投资组合管理、平台战略等系统性工具,将研发投资转化为可持续的商业竞争力。书中强调的“管理即内部因素”理念,揭示了企业规模扩张与管理能力匹配的深层规律,为高科技企业提供了可借鉴…...
failed to load steamui.dll”错误:Steam用户的高频崩溃问题解析
当你满心欢喜地双击 Steam 图标,准备进入游戏世界时,屏幕上突然弹出 “failed to load steamui.dll” 的刺眼提示——这是全球数百万 Steam 用户最不愿见到的错误之一。作为 Steam 客户端的核心界面动态链接库文件,steamui.dll 的缺失或损坏会…...
Linux多线程详解
Linux多线程详解 一、Linux多线程概念1.1 什么是线程1.2 进程和线程1.3 进程的多个线程共享1.4 进程和线程的关系 二、Linux线程控制2.1 POSIX线程库2.2 线程创建2.3 获取线程ID pthread_self2.4 线程等待pthread_join2.5 线程终止2.6 线程栈 && pthread_t2.7 线程的局…...
权限提升—Windows权限提升土豆家族溢出漏洞通杀全系
前言 OK,Java安全更新不下去了,实在是太难啦啊,想起来提权这一块没怎么更新过,接下来都主要是更新提权这一块的文章了,Java安全的话以后有耐心再搞了。 手动提权 今天主要是讲这个手动的提权,手动提权相…...
JVM(基础篇)
一.初识JVM 1.什么是JVM JVM全称Java Virtyal Machine,中文译名 Java虚拟机 。JVM本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件(将字节码解释成机器码)。 2.JVM的功能 解释和运行:对字节码文件中的指令号,实时…...
cf1007-D
__builtin_ctzll(x)可以用((int)log2(x&-x))代替 void solve() {int n;i64 l, r;std::cin >> n >> l >> r;std::vector<int> a(n 1);for (int i 1; i < n; i) {std::cin >> a[i];}std::vector<int> pre(n 1);for (int i 1; i …...
【Unity网络编程知识】使用Socket实现简单TCP通讯
1、Socket的常用属性和方法 创建Socket TCP流套接字 Socket socketTcp new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 1.1 常用属性 1)套接字的连接状态 socketTcp.Connected 2)获取套接字的类型 socketTcp.So…...
深入解析SSL/TLS证书:构建现代网络安全的密码学基石1.1 TLS 1.3握手流程优化
一、协议层深度解析:TLS握手全流程拆解 1.1 TLS 1.3握手流程优化 (此处展示TLS 1.3握手流程图,使用Mermaid语法) Client Server ClientHello (supported_versions, cipher_suites, key_share) ServerHello (selected_version, ci…...
【深度学习】GAN生成对抗网络:原理、应用与发展
GAN生成对抗网络:原理、应用与发展 文章目录 GAN生成对抗网络:原理、应用与发展1. 引言2. GAN的基本原理2.1 核心思想2.2 数学表达2.3 训练过程 3. GAN的主要变体3.1 DCGAN (Deep Convolutional GAN)3.2 CGAN (Conditional GAN)3.3 CycleGAN3.4 StyleGAN…...
Live555+Windows+MSys2 编译Androidso库和运行使用(二,实验篇)
文章目录 实验下载推流服务端版本运行 摘要:书接上回 https://blog.csdn.net/qq_20330595/article/details/146412411?spm1001.2014.3001.5502 我们先做几个试验,方便我们理解rtsp推流,先把采集和播放体验一下,我们最后回到代码…...
树莓派ollama docker报错尝试网上方法
ollama ps运行bash:ollama:未找到命令 sudo curl -sSL https://get.docker.com | sh 显示“连接被对方重置” sudo docker run hello-world测试 sudo: docker找不到命令 ollama pull qwen2:7b push:ollama 未找到命令 安装 docker sudo apt update sudo apt …...
工作杂谈(十七)——研发阶段术语
EVT/DVT/PVT/MP是指在制造行业一个产品研发导入从试产到量产的不同阶段: EVT:Engineering Verification Test工程验证测试阶段 DVT:Design Verification Test设计验证测试 PVT:Production Verification Test 小批量生…...
Spring MVC:从历史演变到实战入门
1. Java Web的发展历史与MVC模式 1.1 Model I与Model II的演进 Model I(JSPJavaBean) 作为早期Java Web开发的主流模式,其核心架构如下: graph LR A[客户端] --> B[JSP页面] B --> C{业务逻辑} C --> D[JavaBean] D -…...
C++中的std::move函数详解:移动语义与资源管理
在C中,std::move 是一个用于将对象转换为右值引用的函数模板,通常用于实现资源的转移(如动态内存、文件句柄等),从而避免不必要的拷贝操作。std::move 是C11引入的一个重要特性,主要用于支持移动语义。 目录…...
2025 polarctf春季个人挑战赛web方向wp
来个弹窗 先用最基础的xss弹窗试一下 <script>alert("xss")</script>没有内容,猜测过滤了script,双写绕过一下 <scrscriptipt>alert("xss")</scscriptript>background 查看网页源代码 查看一下js文件 类…...
RabbitMQ 学习整理1 - 基础使用
项目代码:RabbitMQDemo: 学习RabbitMQ的一些整理 基本概念 RabbitMQ是一种基于AMQP协议的消息队列实现框架RabbitMQ可以用于在系统与系统之间或者微服务节点之间,进行消息缓存,消息广播,消息分配以及限流消峰处理RabbitMQ-Serve…...
分布式渲染与云渲染:技术与应用的黄金搭档
一、核心概念:先区分再关联 分布式渲染是通过多台设备并行计算拆分渲染任务的技术(如将一帧拆分为 64 个小块,64 台电脑同时渲染); 云渲染是基于云计算的渲染服务,本质是分布式渲染的商业化落地—— 用户无…...
