【linux高级IO(二)】多路转接之select详解

news2024/9/28 7:22:24

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Linux从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学更多操作系统知识
  🔝🔝


Linux高级IO

  • 1. 前言
  • 2. 初识select
  • 3. 理解select的执行过程
  • 4. select的简使用示例
  • 5. 总结

1. 前言

多路转接一共有三种实现方案, 分别是select,poll和epoll. 本系列文章会一一讲解它们的优缺点和使用方法. 如果你还不清楚这些IO模型, 请先阅读这篇文章: Linux高级IO

本章重点:

本篇文章着重讲解select函数的原型和用法, 并且会带大家实现一个简单的select多路转接代码


2. 初识select

系统提供select函数来实现多路复用输入/输出模型.

select函数的原型:

在这里插入图片描述

参数解释:

  • 参数nfds是需要监视的最大的文件描述符值+1;
  • rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合;
  • 参数timeout为结构timeval,用来设置select()的等待时间

就绪事件通常分为可读事件,可写事件和异常事件

参数timeout的意义:

  • NULL:则表示select()没有timeout,select将一直被阻塞,直到某个文件描述符上发生了事件;
  • 0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生。
  • 特定的时间值:如果在指定的时间段里没有事件发生,select将超时返回。

select函数参数中, 使用了fd_set类型变量, 如果你对信号部分比较熟悉, 那么你一定能猜到, fd_set是个位图, 你可以把你需要关心的所有fd都设置到这个位图中, 让select函数帮你关心, 比如你想要关心0号文件描述符(stdin)的读事件, 那么就在readfd中将0设置进去.

在这里插入图片描述
select函数的返回值以及错误码:

在这里插入图片描述


3. 理解select的执行过程

timel结构体参数,fd_set类型参数都是输入输出型参数

  • timeval类型参数: 假如你设置阻塞时间为5秒, 但是等待了三秒后就有事件就绪, 函数就返回了, 那么timeval类型参数的值会被设置成为2秒.
  • fd_set类型参数, 输入你想要关心的fd集合, 输出时, 此结构中存放, 已经事件就绪的fd集合. 比如你想要关心0~10号文件描述符的读事件, 函数返回时, 此集合中可能只有1.3.5号fd被返回了, 也就是说只有1.3.5号fd的事件就绪了

综上所述: 每一次调用完select后,都需要我们重置参数

while(1)
{
	 //处理完重置参数
	 fs_set readset;
	 FD_SET(fd,&readset);
	 select(fd+1,&readset,NULL,NULL,NULL);
	 if(FD_ISSET(fd,readset))
	 {……}
}

什么叫做事件就绪?拿读事件来说, 客户端和服务器建立连接后, 客户端就一定会向服务器发送数据吗? 不一定! 所以服务器只能等待客户端发数据, 一旦接收缓冲区有数据到来, 那么就是读事件就绪了, 可以直接调用recv函数从对应的fd中将数据拿到内存. 写事件也是如此, 可能此时的发送缓冲区已满, 那么就需要等待

select的特点:

在这里插入图片描述

fd_set的大小可变,有兴趣可自行查资料

select的缺点:

在这里插入图片描述

正因为select的这些缺陷, 才会有后面的poll和epoll来代替它


4. select的简使用示例

多路转接的编程本质上也是网络编程, 所以我们可以先定义一个sock.h文件用于网络通信的套接字编程:

class Sock
{
    const static int gbacklog = 20;
public:
    Sock()
    {

    }
    static int Socket()
    {
        
    }
    static void Bind(int sock, uint16_t port, string ip = "0.0.0.0")
    {
       
    }
    static void Listen(int sock)
    {
    }
    static int Accept(int listensock,string* ip,uint16_t* port)
    {
        
    }   
    static bool Connect(int sock,string serverip,uint16_t serverport)//客户端要连接谁就传谁的ip和port
    {
        
    }
    ~Sock()
    {}
};

接下来是select的编程:

#ifndef __SELECT_SVR_H__
#define __SELECT_SVR_H__
#include <iostream>
#include <sys/select.h>
#include <vector>
#include "log.hpp"
#include "sock.hpp"
#include <string>
#include <sys/time.h>
using namespace std;

#define BITS 8
#define NUM (sizeof(fd_set) * BITS)
#define FD_NONE -1

// 只完成读取,写入和异常暂时不做处理,单进程,可以同时为多个人服务
class Select_Server
{
public:
    Select_Server(uint16_t port = 9090)
        : _port(port)
    {
        _listensock = Sock::Socket();
        Sock::Bind(_listensock, port);
        Sock::Listen(_listensock);
        logMessage(DEBUG, "创建基础套接字成功!");
        for (int i = 0; i < NUM; i++)
            _array[i] = FD_NONE; // 规定array[0] = _listensock
        _array[0] = _listensock;
    }

    void Start()
    {
        while (1)
        {
            DebugPrint();
            // struct timeval timeout = {5, 0};
            //  如何看待当前唯一的套接字?获取新连接,我们把它依旧看作IO,input事件,如果没有连接到来,调用accept就会阻塞,不能直接调用accept
            //  FD_SET(_listensock, &readfd); // 将listensock添加到文件描述符集合中
            //  int n = select(_listensock + 1, &readfd, nullptr, nullptr, &timeout);
            //  随着获取的sock越来越多,注定了nfds每一次都可能要发送变化,需要对它进行动态计算,并且rfds,writefds是输入输出型参数,每次输入输出可能不同,注定了每次都要对rfds进行重新添加
            //  应该将自己所有的文件描述符都单独保存起来,用来支持: 1. 更新最大值 2. 更新位图结构
            fd_set readfd;
            FD_ZERO(&readfd); // 将这个位图清空
            int maxfd = _listensock;
            for (int i = 0; i < NUM; i++) // 更新位图,寻找最大值
            {
                if (_array[i] == FD_NONE)
                    continue;
                FD_SET(_array[i], &readfd);
                if (_array[i] > maxfd)
                    maxfd = _array[i];
            }
            int n = select(maxfd + 1, &readfd, nullptr, nullptr, nullptr);
            if (n == 0) // 没有文件描述符就绪
                //logMessage(DEBUG, "time out");
            else if (n == -1)
                //logMessage(DEBUG, "select error");
            else
            {
                //logMessage(DEBUG, "select获取到一个链接");
                HandlerEvent(readfd);
            }
        }
    }

    ~Select_Server()
    {
        if (_listensock >= 0)
            close(_listensock);
    }

private:
    void Accepter()
    {

    }

    void Recver(int sock, int pos)
    {
        
    }

    void HandlerEvent(const fd_set &readfd) // fd_set是一个集合,里面可能存在多个sock
    {
        
    }
private:
    uint16_t _port;
    int _listensock;
    int _array[NUM];
};
#endif

关于代码的解释都在注释中, 如果你想查看完整的代码, 可以在gitee: select编程示例中找到你想要的一切

需要注意的是, 读事件就绪有两种情况, 一种是新来fd的连接了, 另外一种是已有的连接的数据就绪了, 所以这两种情况需要分开讨论


5. 总结

为什么多路转接在实际生活中运用如此之多? 答案就是它一次性可以等待多个文件描述符, 效率很高. 但是select多路转接方案有局限性, 所以后面的epoll才是学习的重点


🔎 下期预告:多路转接之poll 🔍

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

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

相关文章

SAP_SD_赠品(买A送B)

TCD:VBN1 例&#xff1a;买一台电脑送一个电脑包 VA01 看效果

错误记录-SpringCloud-OpenFeign测试远程调用

文章目录 1&#xff0c;org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name memberController: Unsatisfied dependency expressed through field couponFeign2&#xff0c; Receiver class org.springframework.cloud.netflix…

帕金森病友,保持心态小秘诀来啦!

大家好&#x1f44b;&#xff0c;今天想和帕友们分享一些保持好心态的小秘诀&#x1f4a1;。虽然帕金森病带给我们不少挑战&#xff0c;但心态可是咱们战胜困难的一大法宝哦&#xff01;&#x1f4aa; &#x1f340;接纳自己 首先&#xff0c;要学会接纳自己。帕金森并不定义我…

2024年有多少程序员转行了?

疫情后大环境下行&#xff0c;各行各业的就业情况都是一言难尽。互联网行业更是极不稳定&#xff0c;频频爆出裁员的消息。大家都说2024年程序员的就业很难&#xff0c;都很焦虑。 在许多人眼里&#xff0c;程序员可能是一群背着电脑、进入高大上写字楼的职业&#xff0c;他们…

HNU计算机系统课程总结与反思

HNU计算机系统这门课程用的是《深入理解计算机系统》第三版&#xff0c;作业题用的是第二版&#xff08;据说23届可能会全面改为第三版...&#xff09;。第三版对应64位系统&#xff0c;第二版对应32位系统&#xff0c;学了64位的反正没有坏处&#xff0c;是向下兼容的。这门课…

官宣定档!2025深圳电子展,开启全球招展工作

随着科技的飞速发展&#xff0c;电子信息产业已成为推动全球经济的重要力量。深圳&#xff0c;作为中国的硅谷&#xff0c;一直以来都是电子信息产业的前沿阵地。2025年&#xff0c;深圳电子展暨深圳国际电子信息博览会再次定档于4月份在深圳会展中心盛大召开&#xff0c;这不仅…

【数据分享】2024年公园绿地数据(全国/分省/分城市/免费获取)

公园绿地数据是我们在各项研究中经常使用的数据&#xff01;公园绿地数据虽然很常用&#xff0c;但是却基本没有能下载最近年份公园绿地数据的网站&#xff0c;所以很多人不知道如何获得公园绿地数据。本次我们为大家推荐的下载道路数据的网站是Open Street Map&#xff01;我们…

Nacos 注册中心和配置中心【实战】

前言&#xff1a; Nacos 是 alibaba 出品的微服务组件&#xff0c;Nacos 支持几乎所有主流类型的服务的发现、配置和服务管理平台&#xff0c;提供注册中心、配置中心和动态DNS服务三大功能&#xff0c;能够无缝对接 Springcloud、Spring、Dubbo等流行框架&#xff0c;本篇我们…

Hugging Face使用笔记

1. HuggingFace简介 Hugging Face Hub和 Github 类似&#xff0c;都是Hub(社区)。Hugging Face可以说的上是机器学习界的Github。Hugging Face为用户提供了以下主要功能&#xff1a; 模型仓库&#xff08;Model Repository&#xff09;&#xff1a;Git仓库可以让你管理代码版…

振弦式渗压计:水库大坝渗流监测的重要仪器

在水利工程领域&#xff0c;水库大坝作为重要的基础设施&#xff0c;其安全性和稳定性直接关系到下游人民的生命财产安全及国家经济的稳定发展。为了确保大坝的安全运行&#xff0c;对水库大坝进行渗流监测显得尤为重要。在众多监测仪器中&#xff0c;振弦式渗压计以其高精度、…

采用前后端分离技术架构+java语言开发的全套产科信息管理系统源码 可与医院HIS、LIS、PACS、RIS等系统进行对接

采用前后端分离技术架构java语言开发的全套产科信息管理系统源码 可与医院HIS、LIS、PACS、RIS等系统进行对接 什么是产科信息管理系统-建档管理&#xff1f; 产科信息管理系统建档管理通过信息技术实现了孕产妇健康信息的电子化、网络化和智能化管理&#xff0c;提高了医疗服…

UV胶水,如同一位技艺高超的魔术师真的不需要时间的洗礼固化吗?

UV胶水&#xff0c;如同一位技艺高超的魔术师真的不需要时间的洗礼固化吗&#xff1f; 导语&#xff1a;UV胶水&#xff0c;如同一位技艺高超的魔术师&#xff0c;难道真的不需要时间的洗礼&#xff0c;便能即刻展现其黏合的魅力吗&#xff1f;并非如此&#xff0c;尽管UV胶水在…

Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统

文章目录 Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统TFTP服务搭建测试 NFS服务搭建测试 uboot配置TFTP服务搭建测试 NFS服务搭建测试 U-BOOT配置 Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统 TFTP服务搭建 sudo apt install tftpd-hpa su…

信创:鲲鹏(arm64)+麒麟(kylin v10)离线部署k8s和kubesphere(含离线部署新方式)

本文将详细介绍&#xff0c;如何基于鲲鹏CPU(arm64)和操作系统 Kylin V10 SP2/SP3&#xff0c;利用 KubeKey 制作 KubeSphere 和 Kubernetes 离线安装包&#xff0c;并实战部署 KubeSphere 3.3.1 和 Kubernetes 1.22.12 集群。 服务器配置 主机名IPCPUOS用途master-1192.168.10…

SPI协议——对外部SPI操作(跨页读写)

关于W25Q32JVSSIQ的详细内容在之前的两篇文章中已经详细介绍&#xff0c;本文不做太多赘述&#xff0c;如果对芯片的了解有缺失的话&#xff0c;可以参考&#xff1a; SPI协议——对外部SPI Flash操作-CSDN博客 SPI协议——读取外部SPI Flash ID_spi flash 读取id-CSDN博客 目录…

[氮化镓]Kevin J. Chen组新作—肖特基p-GaN HEMTs正栅ESD机理研究

这篇文章是发表在《IEEE Electron Device Letters》上的一篇关于Schottky型p-GaN栅极高电子迁移率晶体管&#xff08;HEMTs&#xff09;的正向栅极静电放电&#xff08;ESD&#xff09;机理研究的论文。文章由Jiahui Sun等人撰写&#xff0c;使用了基于碳化硅&#xff08;SiC&a…

铜重量、走线宽度与载流能力是什么关系?

PCB的载流能力是由走线的横截面积和温升决定的。此外&#xff0c;走线的横截面积与走线宽度和铜厚度成正比。那么&#xff0c;这里有一个问题&#xff1a;这个规则是否也适用于载流能力与走线截面积之间的关系&#xff0c;即走线承载能力与其截面积成正比吗&#xff1f; 铜厚度…

揭秘GPT-4o:未来智能的曙光

引言 近年来&#xff0c;人工智能&#xff08;AI&#xff09;的发展突飞猛进&#xff0c;尤其是自然语言处理&#xff08;NLP&#xff09;领域的进步&#xff0c;更是引人注目。在这一背景下&#xff0c;OpenAI发布的GPT系列模型成为了焦点。本文将详细探讨最新的模型GPT-4o&a…

Electron-ViteChat桌面端聊天室|electron31+vite5+pinia2仿微信EXE程序

原创研发Electron31vue3elementPlus仿微信客户端聊天应用。 使用最新跨平台技术electron31.xvite5vue3 setuppinia2element-plus实战开发电脑版聊天室Exe程序。整个聊天程序界面清爽简约&#xff0c;支持展示/收缩侧边栏、electron新开多窗口、换肤等功能。 electron-vitechat支…