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

多路转接之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的参数填充 获取新连接 注意点 -- 通信时的调用函数 添…...

乐鑫安全制造全流程

主要参考资料&#xff1a; 【乐鑫全球开发者大会】DevCon24 #10 &#xff5c;乐鑫安全制造全流程 乐鑫官方文档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

详细解析三个训练调度文件&#xff1a;schedule_1x.py、schedule_2x.py、schedule_20e.py 在深度学习模型训练过程中&#xff0c;训练调度&#xff08;Training Schedule&#xff09;是至关重要的&#xff0c;它决定了模型训练过程中学习率&#xff08;Learning Rate, LR&…...

Android之Handler是如何保证延迟发送的

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

定位信标、基站、标签,定位信标是什么

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

2024国赛数学建模B题完整分析参考论文38页(含模型和可运行代码)

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

Hive是什么?

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

计算机网络:http协议

计算机网络&#xff1a;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 是一个用于可视化动态效应&#xff08;dynamic effect&#xff09;的工具。它特别适用于事件研究&#xff08;event study&#xff09;或双重差分&#xff08;Difference-in-Differences, DID&#xff09;分析。通过一句命令即可展示动态效应&#xf…...

文心一言 VS 讯飞星火 VS chatgpt (342)-- 算法导论23.2 1题

一、对于同一个输入图&#xff0c;Kruskal算法返回的最小生成树可以不同。这种不同来源于对边进行排序时&#xff0c;对权重相同的边进行的不同处理。证明&#xff1a;对于图G的每棵最小生成树T&#xff0c;都存在一种办法来对G的边进行排序&#xff0c;使得Kruskal算法所返回的…...

部署若依Spring boot项目

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

oc打包:权限弹窗无法正常弹出

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

深入理解RxJava:响应式编程的现代方式

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

Maven 依赖漏洞扫描检查插件 dependency-check-maven 的使用

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

2. 下载rknn-toolkit2项目

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

xhr、ajax、axois、fetch的区别

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

【HuggingFace Transformers】OpenAIGPTModel源码解析

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

macOS安装Java和Maven

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

SpringBoot教程(安装篇) | Elasticsearch的安装

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

前端登录鉴权——以若依Ruoyi前后端分离项目为例解读

权限模型 Ruoyi框架学习——权限管理_若依框架权限-CSDN博客 用户-角色-菜单&#xff08;User-Role-Menu&#xff09;模型是一种常用于权限管理的设计模式&#xff0c;用于实现系统中的用户权限控制。该模型主要包含以下几个要素&#xff1a; 用户&#xff08;User&#xff09;…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...

算法250609 高精度

加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...

学习 Hooks【Plan - June - Week 2】

一、React API React 提供了丰富的核心 API&#xff0c;用于创建组件、管理状态、处理副作用、优化性能等。本文档总结 React 常用的 API 方法和组件。 1. React 核心 API React.createElement(type, props, …children) 用于创建 React 元素&#xff0c;JSX 会被编译成该函数…...