多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信
目录
多路转接之select
引入
介绍
fd_set
函数原型
nfds
readfds / writefds / exceptfds
readfds
总结
fd_set操作接口
timeout
timevalue 结构体
传入值
返回值
代码
注意点 -- 调用函数
select的参数填充
获取新连接
注意点 -- 通信时的调用函数
添加新fd到位图中
处理函数
多路转接之select
引入
io本质+io效率本质,5种io模型(介绍,异步/同步区别,阻塞/非阻塞区别)-CSDN博客
以前使用的io接口,既完成等待,又完成拷贝
但在多路转接的io方式中不同,分为两个部分,需要调用两个函数来完成
介绍
select只负责等待,一次可以等待多个fd
- 就像之前钓鱼例子中的d,他拥有多个鱼竿,就相当于等待多个fd
既然可以关注多个fd,自然参数中就要使用其他数据结构了 -- fd_set
fd_set
内核提供的一种数据类型
- 位图
因为fd_set是一个具体的类型
- 既然是类型,就一定有大小
- 有大小就会有比特位的数量
- 也就相当于可以等待的文件fd值和文件数量是有上限的
使用sizeof测试fd_set的大小,得到它是1024个bit
- 所以一次最多等待1024个文件的某个事件
- 这个值随着系统不同会有变化,实际应该动态计算 -- sizeof(fd_set) * 8
函数原型
nfds
要等待的多个fd中的最大值+1
readfds / writefds / exceptfds
等待多个fd的关键,属于输入输出型参数
等待 -- 等待事件就绪
- 事件 -- 一般分为 读/写/有异常
- 只要读写事件就绪,就可以直接完成拷贝操作,不会阻塞住
- 异常事件是例外,需要特殊处理,这里不做介绍
如果想关注某个文件上的读事件,就把该文件的fd设置进readfds
- 其他同理
- 可以关注同一个文件上的多个事件,也可以分顺序地关注,总之设置进相应位图中就行
接下来我们以readfds为例,详细介绍一下,其他位图同理
readfds
fd本身就是从0开始的数字
- 和数组下标/位图均可以一一对应
因为是输入输出型参数:
输入时
- 我们要告诉内核需要关注的fd集,你要帮我关心这些文件上面的读事件 + 这是个位图结构 + fd和位图可以对应
- 所以,可以得出,位图上的比特位位置(从左向右,从0开始) 对应 文件的fd值
- 只要该位设置为1,就是我们想让内核关注该文件
- eg:我们要关注0,1,2,3这四个文件:
输出时
- 内核要告诉我们,关注的fd集中有哪些fd上的读事件已经就绪 + 返回的也是个位图结构
- 所以,对应关系依然没有变,但代表的含义不同
- 如果该位为1,说明该文件上的读事件已经就绪
- 内核会先将位图清零,然后将[读事件已经就绪的文件]的fd值 对应的 比特位 置1
- eg:四个文件中,fd=2的文件的读事件就绪:
总结
所以,总结来说,fd_set这张位图,是让用户和内核之间互相传递信息的
- 那么,在使用select函数的过程中,一定会涉及大量的位图操作
fd_set操作接口
为了让用户更方便,内核为我们提供了接口
timeout
设置select的等待方式
每隔若干秒,timeout一次,timeout后 / 有文件就绪后函数会返回
timevalue 结构体
在gettimeofday()中也有使用这个类型作为参数:
- 获取特定时区下的特定时间,精确到微秒级别
- 时间戳 -- 秒单位和微妙单位
- 比如传入参数{5,0},代表设置时间戳为5s
传入值
- 设置>0 -- 每隔一段时间timeout一次,比如5s
- 设置为0 -- 非阻塞(select立即返回)
- 设置为NULL -- 阻塞等待,直到有文件就绪
如果设置(非NULL)了该时间
- 则为输入输出型参数
- 如果在等待的中途有文件就绪,则返回[timeout时间-已经等待时间],也就是[距离超时时间的剩余时间 ]
返回值
- >0 -- 有n个fd就绪
- =0 -- 超时,等待过程中没有错误,也没有fd就绪
- <0 -- 等待出错(要等待的某个文件已经关闭了)
代码
我们这里实现一个非阻塞版网络通信
注意点 -- 调用函数
创建好套接字后,不能直接accept
- accept本质就是在检测并获取listensock上面的事件
- 但我们这里目的就是要让select去等待事件(有事件了再去通知我们来获取,这时候调用accept就不会被阻塞了)
- 所以不能先调用accept
这里的事件:
- = 新连接到来 = 三次握手完成,系统把新连接投递到全连接队列里 = select里的读事件
- 所以我们先调用select等待读事件
select的参数填充
这里是服务器刚启动时,是我们需要让listensocket检测并获取新连接(新客户端与当前服务器通信)
- 所以,等待的是listensocket上的读事件,并且当前只有这一个套接字
- 所以,max_fd=listensocket_fd+1
- 等有客户端连接后,会有新的套接字被创建(通信时使用的套接字),就需要添加检测这些套接字上的读写事件了(后面会细说)
因为timeout是输入输出型参数
- 一旦超时/当前有事件就绪,就会修改timeout的值
- 所以,为了不影响下一次的等待方式,需要重复设置timeout参数
三个位图集也是同理,需要重复设置
- 不然会被修改成已经就绪的,而不代表需要内核关注的fd集
获取新连接
如果事件就绪,上层却不处理,select会一直通知
- 所以需要我们手动调用accept()去把新连接拿走(这个操作在我们新的处理函数中)
当然,我们无法确定是哪个fd就绪了
- 所以需要先判断
- 判断完成后,就可以拿到新连接,创建新套接字了
注意点 -- 通信时的调用函数
接下来要开始通信了,原先我们的服务器是直接read,但这里不行
- 因为read是阻塞式等待,而我们要实现非阻塞式
- 而且一旦阻塞在这里,就无法获取新连接以及与其他客户端通信了(因为我们写的是单进程)
- 所以,还是需要使用select
添加新fd到位图中
当然,我们不能调用新的select
- 为什么?
- 一般都是在主循环处持续调用select,高效且简洁
- 如果使用多个select,会导致代码逻辑复杂化,也难以管理
所以,需要我们把这个新套接字的fd设置进刚才的select的位图中
- 这一过程就相当于d在不断增加自己鱼竿的数量
但是,这两个数据在不同的函数中(我们在处理函数中获取新连接,而select的使用在主逻辑函数中),如何传递呢?
- 因为这两个函数都在类中,所以我们搞一个类内变量 -- 辅助数组
- 让新增的fd都添加进辅助数组中,然后让select每次动态设置max_fd,以及三个位图
可以固定监听套接字(也就是我们创建的第一个套接字)作为数组的第一项
- 方便我们后续区分[获取新连接] 和 [读写事件]
因为在过程中,可能会陆陆续续关掉一些文件
- 所以原本添加进的连续fd,会变成零零星星的
- 所以,需要我们每次都重新整理一下这个数组,把有效的fd统一放在左侧
我们每次在循环开头就处理数组中的值
- 合法的fd就让它设置进位图中
- 不仅如此,在这个过程中,我们还可以找到fd中的最大值,来填充select参数
解决了如何添加新fd的问题,接下来回到处理函数
处理函数
当我们识别到有事件就绪,获取连接后获得新套接字fd,之后就该将该fd设置进辅助数组中了
- 需要我们遍历数组,找到空位(值为-1/其他你设定的[数组内的初始值]),然后添加进去
更新ing...
相关文章:

多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信
目录 多路转接之select 引入 介绍 fd_set 函数原型 nfds readfds / writefds / exceptfds readfds 总结 fd_set操作接口 timeout timevalue 结构体 传入值 返回值 代码 注意点 -- 调用函数 select的参数填充 获取新连接 注意点 -- 通信时的调用函数 添…...

乐鑫安全制造全流程
主要参考资料: 【乐鑫全球开发者大会】DevCon24 #10 |乐鑫安全制造全流程 乐鑫官方文档Flash加密: https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/security/flash-encryption.html 【ESP32S3】使用 Flash 下载工具完成 Flash 加密功能…...

〖open-mmlab: MMDetection〗解析文件:configs/_base_/schedules
详细解析三个训练调度文件:schedule_1x.py、schedule_2x.py、schedule_20e.py 在深度学习模型训练过程中,训练调度(Training Schedule)是至关重要的,它决定了模型训练过程中学习率(Learning Rate, LR&…...

Android之Handler是如何保证延迟发送的
目录 核心组件延迟发送消息的工作原理具体步骤1. 创建 Handler:2.发送延迟消息3.消息入队列4.消息出队和处理: 关键点总结 在 Android 中,Handler 是用于在不同线程之间传递和处理消息的工具。它可以用于定时任务、延迟执行任务等。Handler 如何保证延迟发送消息的核…...

定位信标、基站、标签,定位信标是什么
定位信标、基站、标签,定位信标是什么 今天给各位分享定位信标、基站、标签的知识,其中也会对定位信标是什么进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧! 怎样做人员定位啊? 〖…...

2024国赛数学建模B题完整分析参考论文38页(含模型和可运行代码)
2024 高教社杯全国大学生数学建模完整分析参考论文 B 题 生产过程中的决策问题 目录 摘要 一、问题重述 二、问题分析 三、 模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码(仅供参考) 4.…...

Hive是什么?
Apache Hive 是一个基于 Hadoop 的数据仓库工具,用于在 Hadoop 分布式文件系统(HDFS)上管理和查询大规模结构化数据集。Hive 提供了一个类似 SQL 的查询语言,称为 HiveQL,通过这种语言可以在 HDFS 上执行 MapReduce 作…...

计算机网络:http协议
计算机网络:http协议 一、本文内容与前置知识点1. 本文内容2. 前置知识点 二、HTTP协议工作简介1. 特点2. 传输时间分析3. http报文结构 三、HTTP版本迭代1. HTTP1.0和HTTP1.1主要区别2. HTTP1.1和HTTP2主要区别3. HTTPS与HTTP的主要区别 四、参考文献 一、本文内容…...

【stata】自写命令分享dynamic_est,一键生成dynamic effect
1. 命令简介 dynamic_est 是一个用于可视化动态效应(dynamic effect)的工具。它特别适用于事件研究(event study)或双重差分(Difference-in-Differences, DID)分析。通过一句命令即可展示动态效应…...

文心一言 VS 讯飞星火 VS chatgpt (342)-- 算法导论23.2 1题
一、对于同一个输入图,Kruskal算法返回的最小生成树可以不同。这种不同来源于对边进行排序时,对权重相同的边进行的不同处理。证明:对于图G的每棵最小生成树T,都存在一种办法来对G的边进行排序,使得Kruskal算法所返回的…...

部署若依Spring boot项目
nohup和& nohup命令解释 nohup命令:nohup 是 no hang up 的缩写,就是不挂断的意思,但没有后台运行,终端不能标准输入。 nohup :不挂断的运行,注意并没有后台运行的功能,就是指,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系,注意了nohup没有后台…...

oc打包:权限弹窗无法正常弹出
在遇到编写了权限无法弹出弹窗时,需要查看是不是调用时机不对,这里直接教万能改法。 将权限获取方法编写在applicationDidBecomeActive 进入前台的生命周期接口中,如下: if (@available(iOS 14, *)) {NSLog<...

深入理解RxJava:响应式编程的现代方式
在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJ…...

Maven 依赖漏洞扫描检查插件 dependency-check-maven 的使用
前言 在现代软件开发中,开源库的使用愈加普遍,然而这些开源库中的漏洞往往会成为潜在的安全风险。如何及时的发现依赖的第三方库是否存在漏洞,就变成很重要了。 本文向大家推荐一款可以进行依赖包漏洞检查的 maven 插件 dependency-check-m…...

2. 下载rknn-toolkit2项目
官网链接: https://github.com/airockchip/rknn-toolkit2 安装好git:[[1. Git的安装]] 下载项目: git clone https://github.com/airockchip/rknn-toolkit2.git或者直接去github下载压缩文件,解压即可。...

xhr、ajax、axois、fetch的区别
一、XMLHttpRequest (XHR)、AJAX、Axios 和 Fetch API 都是用于在不重新加载整个页面的情况下与服务器进行通信的技术和库。它们在处理超时、终止请求、进度反馈等机制上有一些显著的差异。以下是它们的详细比较: 1. XMLHttpRequest (XHR) XMLHttpRequest 是一种浏…...

【HuggingFace Transformers】OpenAIGPTModel源码解析
OpenAIGPTModel源码解析 1. GPT 介绍2. OpenAIGPTModel类 源码解析 说到ChatGPT,大家可能都使用过吧。2022年,ChatGPT的推出引发了广泛的关注和讨论。这款对话生成模型不仅具备了强大的语言理解和生成能力,还能进行非常自然的对话,…...

macOS安装Java和Maven
安装Java Java Downloads | Oracle 官网下载默认说最新的Java22版本,注意这里我们要下载的是Java8,对应的JDK1.8 需要登陆Oracle,没有账号的可以百度下。账号:908344069qq.com 密码:Java_2024 Java8 jdk1.8配置环境变量 open -e ~/.bash_p…...

SpringBoot教程(安装篇) | Elasticsearch的安装
SpringBoot教程(安装篇) | Elasticsearch的安装 一、确定Elasticsearch版本二、下载elasticsearch(windows版本)官网下载如何解压配置 允许 别人跨域 访问自己启动运行 三、Es可视化工具安装(elasticsearch-head&#…...

前端登录鉴权——以若依Ruoyi前后端分离项目为例解读
权限模型 Ruoyi框架学习——权限管理_若依框架权限-CSDN博客 用户-角色-菜单(User-Role-Menu)模型是一种常用于权限管理的设计模式,用于实现系统中的用户权限控制。该模型主要包含以下几个要素: 用户(User)…...

【Tools】大模型中的自注意力机制
摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样 🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一…...

PhotoZoom Classic 9软件新功能特性及安装激活图文教程
PhotoZoom Classic 9这款软件能够对数码图片进行放大,而且放大后的图片没有任何的品质的损坏,没有锯齿,不会失真,如果您有兴趣的话可以试试哦! PhotoZoom Classic 9软件新功能特性 通过屡获殊荣的 S-Spline XL 插值…...

【数据结构】直接插入排序
目录 一、基本思想 二、动图演示 三、思路分析 四、代码实现 五、易错提醒 六、时间复杂度分析 一、基本思想 直接插入排序(Straight Insertion Sort)是一种简单直观的排序算法,其基本思想是: 把待排序的一个记录按其关键码…...

JavaScript 实现虚拟滚动技术
虚拟滚动 虚拟滚动(有时称为 虚拟列表、虚拟滚动条)是 JavaScript 中的一种技术,旨在优化大数据量的列表渲染,尤其是当有成千上万的数据项时,直接渲染整个列表会导致性能问题。虚拟列表通过只渲染用户视口中可见的那一…...

【重学 MySQL】十八、逻辑运算符的使用
【重学 MySQL】十八、逻辑运算符的使用 AND运算符OR运算符NOT运算符异或运算符使用 XOR 关键字使用 BIT_XOR() 函数注意事项 注意事项 在MySQL中,逻辑运算符是构建复杂查询语句的重要工具,它们用于处理布尔类型的数据,进行逻辑判断和组合条件…...

关于 QImage原始数据格式与cv::Mat原始数据进行手码数据转换 的解决方法
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141996117 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

前端WebSocket客户端实现
// 创建WebSocket连接 var socket new WebSocket(ws://your-spring-boot-server-url/websocket-endpoint);// 连接打开时触发 socket.addEventListener(open, function (event) {socket.send(JSON.stringify({type: JOIN, room: general})); });// 监听从服务器来的消息 socke…...

读取realsense d455双目及imu
问题定义 实时读取realsense数据喂给slam系统 代码 /** rs_d455设备 */#include <librealsense2/rs.hpp> #include <iostream>#include "rs_common_device.h"// opencv #include <opencv2/opencv.hpp>class RsD455Device: public rsCmmonDevice…...

浮点的运算
浮点数表示: N 尾数 * 基数指数 1.25 X 106 尾数一般用补码,指数一般用移码 在IEEE745中尾数可以是原码。 尾数可以表示数值的有效精度,位数越多精度越高 阶码的位数决定数的表示范围,位数越多,范围越大 对阶时&…...

对随机游走问题的分析特定行为模式的建模
从一段随机游走的数据中寻找特定的行为模式,这种问题涉及 序列模式识别 或 序列分析。处理这种问题的算法选择取决于你要找的模式的具体性质和复杂性。以下是几种可能的算法: 隐马尔可夫模型(HMM) 隐马尔可夫模型特别适合处理随…...