4.26和4.27、selectAPI介绍(4.27、select代码)

news2024/9/21 16:37:04

4.26和4.27、selectAPI介绍(4.27、select代码)

  • 1.selectAPI介绍
    • ①select多路复用流程图
    • ②select多路复用缺点
  • 2.select代码使用介绍
  • 3.select代码实现
    • ①select服务端实现
    • ②select客户端实现

1.selectAPI介绍

主旨思想:

  1. 首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。
  2. 调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O操作时,该函数才返回。
    • a:这个函数是阻塞
    • b:函数对文件描述符的检测的操作是由内核完成的
  3. 在返回时,它会告诉进程有多少(哪些)描述符要进行I/O操作。

在这里插入图片描述

①select多路复用流程图

在这里插入图片描述

②select多路复用缺点

在这里插入图片描述

2.select代码使用介绍

// sizeof(fd_set) = 128 1024
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
	- 参数:
		- nfds : 委托内核检测的最大文件描述符的值 + 1
		- readfds : 要检测的文件描述符的读的集合,委托内核检测哪些文件描述符的读的属性
				- 一般检测读操作
				- 对应的是对方发送过来的数据,因为读是被动的接收数据,检测的就是读缓冲区
				- 是一个传入传出参数
				
		- writefds : 要检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性
				- 委托内核检测写缓冲区是不是还可以写数据(不满的就可以写)
				
		- exceptfds : 检测发生异常的文件描述符的集合
		- timeout : 设置的超时时间
			struct timeval {
				long tv_sec; /* seconds */
				long tv_usec; /* microseconds */
			};
			- NULL : 永久阻塞,直到检测到了文件描述符有变化
			- tv_sec = 0 tv_usec = 0, 不阻塞
			- tv_sec > 0 tv_usec > 0, 阻塞对应的时间
	- 返回值 :
		- -1 : 失败
		- >0(n) : 检测的集合中有n个文件描述符发生了变化
		
// 将参数文件描述符fd对应的标志位设置为0
void FD_CLR(int fd, fd_set *set);
// 判断fd对应的标志位是0还是1, 返回值 : fd对应的标志位的值,0,返回0, 1,返回1
int FD_ISSET(int fd, fd_set *set);
// 将参数文件描述符fd 对应的标志位,设置为1
void FD_SET(int fd, fd_set *set);
// fd_set一共有1024 bit, 全部初始化为0
void FD_ZERO(fd_set *set);

3.select代码实现

①select服务端实现

#include <iostream>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <cstring>

using namespace std;

int main() {


    // 创建监听文件描述符
    int server_listen_fd = socket(PF_INET, SOCK_STREAM, 0);


    sockaddr_in server_addr;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9999);
    // 绑定ip和端口
    bind(server_listen_fd, (sockaddr *)&server_addr, sizeof(server_addr));

    // 监听
    listen(server_listen_fd, 8);

    // 创建fd_set集合
    fd_set read_set, tmp;
    FD_ZERO(&read_set);
    FD_SET(server_listen_fd, &read_set);

    // 定义最大的文件描述符
    int max_fd = server_listen_fd;

    while (1) {
        
        // 因为select会修改read_set的值,所以定义一个中间变量
        tmp = read_set;

        // 返回值为多少个文件描述符中的读端数据发生了变化
        int select_len = select(max_fd + 1, &tmp, NULL, NULL, NULL);

        if (select_len == -1) {
            perror("select");
            exit(-1);
        } else if (select_len == 0) {
            // 当等待时间 timeVal 的值还没观察到变化才返回0,这里不存在
            continue;
        } else if (select_len > 0) { // 观察到变化

            // 监听文件描述符发生变化
            if (FD_ISSET(server_listen_fd, &tmp)) {

                sockaddr_in client_addr;
                socklen_t client_len = sizeof(client_addr);

                // 获取客户端的ip和地址
                int client_fd = accept(server_listen_fd, (sockaddr *)&client_addr, &client_len);

                // 新进来的文件描述符加进集合中
                FD_SET(client_fd, &read_set);
                max_fd = max(max_fd, client_fd);

            }

            // 遍历每一个文件描述符
            for (int i = server_listen_fd + 1; i <= max_fd; i ++ ) {

                if (FD_ISSET(i, &tmp)) {

                    char buf[1024] = {0};
                    // 接受客户端的消息
                    int recv_ret = recv(i, buf, sizeof(buf), 0);
                    if (recv_ret == -1) {
                        perror("recv");
                        exit(-1);
                    } else if (recv_ret == 0) {
                        cout << "client closed..." << endl;
                        FD_CLR(i, &read_set);
                        continue;
                    } else if (recv_ret > 0) {
                        printf("I am server, data: %s\n", buf);
                    }

                    // 向客户端回复数据
                    send(i, buf, strlen(buf) + 1, 0);

                }

            }

        }
        
    }

    return 0;
}

②select客户端实现

#include <iostream>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstring>

using namespace std;

int main()
{
    // 1.创建客户端socket
    int client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd == -1) {
        perror("socket");
        exit(-1);
    }

    // 2.连接服务端
    // 设置需要连接的服务器的 ip 和端口
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;   // 设置为ipv4协议
    // 将点分十进制ip转换为newwork字节序
    int pton_ret = inet_pton(AF_INET, "xxx.xxx.xxx.xxx", &server_addr.sin_addr.s_addr);
    // 将主机序端口转换为newwork字节序端口
    server_addr.sin_port = htons(9999);

    int cone_ret = connect(client_fd, (sockaddr *)&server_addr, sizeof(server_addr));
    if (cone_ret == -1) {
        perror("connect");
        exit(-1);
    }

    // 3.读写服务端数据
    int num = 0;
    char recvBuf[1024] = {0};
    while (1) {
        
        // 往服务端写数据
        sprintf(recvBuf, "hello, I am client: %d\n", num ++ );
        write(client_fd, recvBuf, strlen(recvBuf) + 1);


        // 接手服务端数据
        int read_ret = read(client_fd, recvBuf, sizeof(recvBuf));
        if (read_ret == -1) {
            perror("read");
            exit(-1);
        } else if (read_ret > 0) {
            printf("recv client data is %s\n", recvBuf);
        } else if (read_ret == 0){
            cout << "server closed..." << endl;
            break;
        }
        sleep(1);

    }

    // 关闭文件描述符
    close(client_fd);

    return 0;
}

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

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

相关文章

FreeRTOS 其他任务 API 函数

文章目录 一、任务相关 API 函数预览二、任务相关 API 函数详解1. 函数 uxTaskPriorityGet()2. 函数 vTaskPrioritySet()3. uxTaskGetSystemState()4. 函数 vTaskGetInfo()5. 函数 xTaskGetApplicationTaskTag()6. 函数 xTaskGetCurrentTaskHandle()7. 函数 xTaskGetHandle()8.…

(十二)rk3568 NPU 中部署自己训练的模型,(1)使用yolov5训练自己的数据集-模型训练部分

一、rknn的demo中已经给了yolov5的后处理demo。但是这个后处理只适合yolov5特定版本(v5.0),还有下载特定的分支,如下为下载位置:。 下载地址 ONNX > CoreML > TFLite">GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > T…

LeetCode 27.移除元素

文章目录 &#x1f4a1;题目分析&#x1f4a1;解题思路&#x1f6a9;思路1:暴力求解 --- 遍历&#x1f514;接口源码&#xff1a;&#x1f6a9;思路2:空间换时间&#x1f514;接口源码&#xff1a;&#x1f6a9;思路3:双指针&#xff08;快慢指针&#xff09;&#x1f514;接口…

Linux系统之部署Samba服务

Linux系统之部署Samba服务 一、Samba服务介绍1.Samba服务简介2.NFS和CIFS简介3.Smaba服务相关包4.samba监听端口4.samba相关工具及命令 二、环境规划介绍1.环境规划2.本次实践介绍 三、Samba服务端配置1.检查yum仓库2.安装smaba相关软件包3.创建共享目录4.设置共享目录权限5.新…

Adobe认证证书

Adobe认证证书是Adobe公司颁发的一种专业认证证书&#xff0c;用于证明持有人在相关Adobe软件的使用和应用方面具有专业水平。该证书是业内公认的专业认证&#xff0c;具有较高的价值和认可度&#xff0c;可以帮助持有人提高职业竞争力和工作效率。 Adobe公司提供了多种认证考…

CentOS7(三)MySQL8 Redis7 (单机)安装

文章目录 一、MySQL安装1、确认是否有老版本2、在线安装3、本地安装 二、启动MySQL三、MySQL常用配置1、密码修改2、配置远程登录3、开启防火墙 3306 端口4、 报错5、MySQL中Java写入时间少14小时 四、Redis 安装1、安装Redis依赖2、启动redis3、指定配置启动 & 后台运行4、…

手机端H5地图调起开发实战案例解析(百度高德腾讯地图调起、底部弹出层、提示安装地图导航APP)

文章目录 1.导航菜单配置构建导航菜单容器设置取消事件调起菜单样式表 2.地图调起事件导航到这里获取导航坐标百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换 3.地图调起效果 地图调起功能&#xff0c;是地图URI API是为开发者提供直接调起地图产品&#xff08;手机客户端&a…

nextjs13临时笔记

动态路由 文件夹以中括号命名[id] -pages: --list: ---[id]: ----index.jsx(访问路径/list/1 即这种形式/list/:id) ---index.jsx(访问路径/list)[...params]gpt接口分析 初始化项目 npm install next react react-dom # or yarn add next react react-dom # or pnpm add n…

WPF教程(六)--依赖属性(2)--属性值优先级与继承

一、 依赖属性的优先级 由于WPF 允许我们可以在多个地方设置依赖属性的值&#xff0c;所以我们就必须要用一个标准来保证值的优先级别。比如下面的例子中&#xff0c;我们在三个地方设置了按钮的背景颜色&#xff0c;那么哪一个设置才会是最终的结果呢&#xff1f;是Black、Re…

[oeasy]python0136_接收输入_input函数_字符串_str

输入变量 回忆上次内容 上次研究了 一行赋值多个变量 a b 5a, b 7, 8 还研究了 标识符的惯用法 python使用的是 snake_case蛇形命名法用下划线 分隔开小写字母的 方法这样就可以 更合理地 命名变量了 变量变量 能变的量我可以 手工输入变量的值 吗&#xff1f;&#x1f9…

MongoDB 数据库数据导入 - 关于如何使用 csv 导入数据的命令方法、图形界面可视化导入方法

序言 兴趣使然&#xff0c;突发奇想&#xff0c;想到了就写&#xff0c;就当打发时间了。 一、使用 csv 导入数据的命令方法 csv文件路径问题&#xff0c;绝对路径和相对路径都可以 方法1 type 没有号&#xff0c;也是可以的&#xff0c;空格自动识别 将测试表.csv 文件导…

pikachu靶场-csrf

csrf 跨站请求伪造&#xff08;英语&#xff1a;Cross-site request forgery&#xff09;&#xff0c;也被称为 one-click attack 或者 session riding&#xff0c;通常缩写为 CSRF 或者 XSRF&#xff0c; 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方…

【C++ 六】内存分区、引用

内存分区、引用 文章目录 内存分区、引用前言1 内存分区模型1.1 程序运行前1.2 程序运行后1.3 new 操作符 2 引用2.1 引用基本使用2.2 引用注意事项2.3 引用做函数参数2.4 引用做函数返回值2.5 引用本质2.6 常量引用 总结 前言 本文包含内存分区、引用基本使用、引用注意事项、…

记一次完整的rc.local中启动python脚本报psutil找不到问题解决

文章目录 1&#xff0c;问题1.1&#xff0c;rc.local1.2&#xff0c;watchdog.py 2&#xff0c;问题排查2.1&#xff0c;手动执行start.sh后功能正常2.2&#xff0c;开机启动后rc.local加载start.sh&#xff0c;然后start.sh启动python脚本报错2.3&#xff0c;怀疑是rc.local加…

SAP S/4HANA不是ERP了?

今天浏览了一下SAP官方帮助&#xff08;Help&#xff09;网站&#xff0c;有一个意外的发现&#xff0c;如上图&#xff1a;SAP S/4HANA和SAP ERP是分别显示的&#xff0c;这让我想起了前段时间一个朋友和我说&#xff1a;“S/4HANA现在都不叫ERP了&#xff0c;因为里面包括了超…

【C++初阶】C++入门(一):命名空间C++的输入输出缺省参数函数重载

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 1.什么是C1.1 C的发…

最新Tuxera NTFS2023最新版Mac读写NTFS磁盘工具 更新详情介绍

Tuxera NTFS for Mac是一款Mac系统NTFS磁盘读写软件。在系统默认状态下&#xff0c;MacOSX只能实现对NTFS的读取功能&#xff0c;Tuxera NTFS可以帮助MacOS 系统的电脑顺利实现对NTFS分区的读/写功能。Tuxera NTFS 2023完美兼容最新版本的MacOS 11 Big Sur&#xff0c;在M1芯片…

Python统计学:如何理解样本统计量?

本期介绍样本统计量是怎么算的&#xff0c;并用Python来模拟随机抽样。用一个在鱼塘捞鱼的简单例子来理解样本均值的概念。 如何理解重复试验&#xff1f; 指能够在完全相同条件下进行多次的试验&#xff1b; 比如我们抛10枚硬币&#xff0c;用来计算正面出现的概率&#xff…

4.7 贝塞尔曲线

学习目标&#xff1a; 学习贝塞尔曲线可以遵循以下步骤&#xff1a; 1.了解基本概念和定义&#xff1a;学习贝塞尔曲线前需要了解贝塞尔曲线的基本概念和定义&#xff0c;如何定义一条贝塞尔曲线、控制点的概念以及贝塞尔曲线的几何性质等。 2.学习贝塞尔曲线的构造方法&…

Django搭建一个简易GPT网站

文章目录 环境安装创建主项目和应用程序在 settings.py 文件中注册应用程序在 views.py 文件中为应用程序创建视图配置应用程序的 URL创建和渲染模板KEY实现发送提示功能注意事项完整源码 环境安装 pip install django openai创建主项目和应用程序 处理完项目的环境后&#x…