day34
1 非阻塞型IO
让我们的read函数不再阻塞,无论是否读取到消息,立刻返回
1.1 fcntl函数
原型:int fcntl(int fd, int cmd, ... /* arg */ );
调用:int flag = fcntl(描述符,F_GETFL)
fcntl(描述符,F_SETFL,flag)
功能描述:设置或者获取文件的各项属性,到底如何操作由cmd决定,一般我们都会用来设置阻塞或者非阻塞IO
参数解析:
参数 fd:准备设置属性的文件的描述符
参数 cmd:文件到底设置什么属性又cmd决定
参数 ...:
F_SETFL:设置文件的flag属性
F_GETFL:获取当前文件的flag属性

2 多路文件IO
能够实现效果:先发生输入事件,再去调用阻塞型的读取函数
例如:
正常情况下,都是先调用scanf函数,阻塞并等待键盘输入事件
如果使用了多路文件IO的话,就能实现:先发生键盘输入事件,事件发生之后,立刻调用scanf函数,直线了高效率且非阻塞
2.1 多路文件IO的工作原理
内核会监视目标套接字的缓存区变化:如果
① 缓存区发生了改变:边缘触发
② 缓存区存在数据:水平触发
内核就会通知监视者,有描述符是可读的
已下3个模型,都是上述工作方式
2.2 select 模型
原型:int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
调用:select(FD_SETSIZE,描述符集合,0,0,0)
FD_SETSIZE:值为1024
功能描述:以阻塞的形式监视 readfds,writefds,exceptfds 这3个描述符集合中,所有描述符,如果有任何描述符激活,则select解除阻塞
参数解析:
参数 nfds:readfds,writefds,exceptfds 这3个集合中的最大值
参数 readfds:监视描述符集合中任意的描述符是否可读,一般我们只用这个
参数 writefds:监视描述符集合中任意的描述符是否可写,一般写NULL
参数 exceptfds:监视描述符集合中任意的描述符是否发生意外,一般写NULL
注意:只要select监视到了有描述符激活,就会将激活的描述符,以覆盖的形式写入到上述3个fds里面去
参数 timeout:是一个结构体,结构如下
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
表示select函数只阻塞传入的时间长度的秒数,超过这个时间自动解除阻塞
传NULL表示:一直阻塞,不受时间影响
返回值:返回激活的描述符的数量
如何操作描述符集合
void FD_CLR(int fd, fd_set *set);
功能描述: 从 set 中删除描述符 fd
int FD_ISSET(int fd, fd_set *set);
功能描述:判断 set 中是否存在描述符 fd
返回值:如果存在返回1,不存在返回0
void FD_SET(int fd, fd_set *set);
功能描述:将描述符 fd 添加到 set 里面去
void FD_ZERO(fd_set *set);
功能描述:清空 set 所有描述符,相当于初始化的功能
select多并发服务器
select代码模型
fd_set readfds;
FD_ZERO(readfds)
FD_SET(想要监视的描述符,readfds)
while(1){
select()
判断/循环判断哪个描述符激活了{
调用对用的阻塞函数
例如:accept 或者 read
}
}
如何操作描述符集合
void FD_CLR(int fd, fd_set *set);
功能描述: 从 set 中删除描述符 fd
int FD_ISSET(int fd, fd_set *set);
功能描述:判断 set 中是否存在描述符 fd
返回值:如果存在返回1,不存在返回0
void FD_SET(int fd, fd_set *set);
功能描述:将描述符 fd 添加到 set 里面去
void FD_ZERO(fd_set *set);
功能描述:清空 set 所有描述符,相当于初始化的功能

select多并发服务器

2.3 poll模型
工作方式和select是一样的,都是用来监视描述符是否激活,只不过操作过程不一样
因为select的不足,才会有poll模型的
① select中 fd_set 类型大小固定,1024个,如果要监视的描述符数量超过1024个,就会有问题
② select监视到激活的描述符成功后,会将激活的把readfds覆盖
poll 解决了上述2个问题
原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
调用:poll(准备监视的struct pollfd 数组,数组的容量/实际长度,-1)
功能描述:监视 fds所指向的描述符数组中所有描述符的情况,最多监视nfds个,一般就是数组的容量
参数解析:
参数 fds:结构体数组,数组中的每一个结构体元素都是一个描述符搭配一些其他数据,结构如下
struct pollfd {
int fd; /* file descriptor */要监视的描述符
short events; /* requested events */可读、可写、意外
因为可读的原因激活:POLLIN,一般我们都写这个
因为可写的原因激活:POLLOUT
short revents; /* returned events */
fd描述符,一旦激活,用来表示具体因为什么原因激活的
};
参数 nfds:想要监视的描述符的数量,一般就是fds这个数组的实际长度
参数 timeout:poll函数阻塞时长,单位为毫秒
传 0 表示不阻塞
传 -1 表示一直阻塞,直到有描述符激活
返回值:成功返回激活的描述符的数量
注意:poll函数监视的直接是一个结构体数组,这个数组我们是可以直接操作的,不需要额外的函数去操作
注意:poll的激活方式为水平触发
水平触发:只要监视的所有套接字中,有任何套接字缓存区存在数据,则poll就会激活
poll的代码模型
struct pollfd fds[n] = {0};
fds[0].fd = 想要监视的第一个描述符
fds[0].events = POLLIN
while(1){
poll(fds,n,-1)
for(遍历 fds){
// 判断 fds中哪个描述符激活了
if(fds[i].revents == POLLIN){
调用对应的阻塞函数
例如 accept 或者 read 或者 scanf等
}
}
}

服务器和2个客户端互相聊天,服务器和客户端都需要使用select模型去实现
在不开线程的情况下,实现互相聊天
服务端
#include <myhead.h>
#define SER_PORT 6666 //服务器端口号
#define SER_IP "192.168.0.129" //服务器ip地址int main(int argc, const char *argv[])
{int client_arr[100] = {0};int len = 0;//1、创建套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);//参数1:表示ipv4的网络通信//参数2:表示使用的是TCP通信方式//参数3:表示默认使用一个协议if (sfd == -1){perror("socket error");return -1;}printf("socket success, sfd = %d\n", sfd); //3//将端口号快速重用int reuse = 1;if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、为套接字绑定ip地址和端口号//2.1 填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //通信域sin.sin_port = htons(SER_PORT); //端口号sin.sin_addr.s_addr = inet_addr(SER_IP); //ip地址//2.2 绑定工作if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success\n");//3、将套接字设置成被动监听状态if (listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success\n");//4、阻塞等待客户端的连接请求//4.1 定义变量用于接收客户端的信息fd_set rdset;FD_ZERO(&rdset);FD_SET(sfd, &rdset);FD_SET(STDIN_FILENO, &rdset);while (1){fd_set temp = rdset;select(FD_SETSIZE, &temp, 0, 0, 0);if (FD_ISSET(sfd, &temp)){int client = accept(sfd, 0, 0);printf("有新客户端链接\n");FD_SET(client, &rdset);client_arr[len] = client;len++;}else if (FD_ISSET(STDIN_FILENO, &temp)){char buf[128] = "";printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;for (int i = 0; i < len; i++){int client = client_arr[i];send(client, buf, 128, 0);}}for (int i = 0; i < len; i++){int client = client_arr[i];if (FD_ISSET(client, &temp)){char buf[128] = "";int res = read(client, buf, 128);if (res == 0){printf("有客户端断开\n");FD_CLR(client, &rdset);for (int j = i; j < len - 1; j++){client_arr[j] = client_arr[j + 1];}len--;close(client);break;}printf("%s\n", buf);}}}return 0;
}
客户端
#include <myhead.h>
#define SER_POPT 6666
#define SER_IP "192.168.0.129"
#define CLI_POPT 8888
#define CLI_IP "192.168.0.129"
int main(int argc, const char *argv[])
{int cfd = socket(AF_INET, SOCK_STREAM, 0);if (cfd == -1){perror("socket error");return -1;}printf("cfd =%d\n", cfd);int reuse = 1;if (setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("reuse error");return -1;}struct sockaddr_in cin;cin.sin_family = AF_INET; //通信域 //端口号cin.sin_addr.s_addr = inet_addr(CLI_IP); //ip地址//2.2 绑定工作if (bind(cfd, (struct sockaddr *)&cin, sizeof(cin)) == -1){perror("bind error");return -1;}printf("bind success\n");struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_POPT);sin.sin_addr.s_addr = inet_addr(SER_IP);if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("connect error");return -1;}fd_set rdset;FD_ZERO(&rdset);FD_SET(cfd, &rdset);FD_SET(STDIN_FILENO, &rdset);while (1){fd_set temp = rdset;select(FD_SETSIZE, &temp, 0, 0, 0);if (FD_ISSET(cfd, &temp)){char buf[128] = "";recv(cfd, buf, 128, 0);printf("%s\n", buf);}else if (FD_ISSET(0, &temp)){char buf[128] = "";printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;send(cfd, buf, strlen(buf), 0);printf("success\n");}}return 0;
}
相关文章:
day34
1 非阻塞型IO 让我们的read函数不再阻塞,无论是否读取到消息,立刻返回 1.1 fcntl函数 原型:int fcntl(int fd, int cmd, ... /* arg */ ); 调用:int flag fcntl(描述符,F_GETFL) fcntl(描述符,F_SETFL&am…...
无缝融入,即刻智能[三]:Dify-LLM平台知识库构建(多路召回、精排重排),43K+星标见证专属智能方案
无缝融入,即刻智能[三]:Dify-LLM平台知识库构建(多路召回、精排重排),43K+星标见证专属智能方案 大语言模型的训练数据一般基于公开的数据,且每一次训练需要消耗大量算力,这意味着模型的知识一般不会包含私有领域的知识,同时在公开知识领域存在一定的滞后性。为了解决这一…...
AWS服务WAF
在 AWS 中使用 Web Application Firewall (WAF) 来防御常见的攻击手段,如 DDoS 攻击和 SQL 注入攻击,可以通过创建和配置规则来实现。下面是如何使用 AWS WAF 阻止这些常见攻击的详细操作步骤。 1. 登录到 AWS 管理控制台 打开 AWS 管理控制台。使用你…...
二叉树中的奇偶树问题
目录 一题目: 二思路汇总: 1.二叉树层序遍历: 1.1题目介绍: 1.2 解答代码(c版): 1.3 解答代码(c版): 1.4 小结一下: 2.奇偶树分析…...
GD - EmbeddedBuilder - 用DMA进行串口发送接收,支持接收不定长包
文章目录 GD - EmbeddedBuilder - 用DMA进行串口发送接收,支持接收不定长包概述笔记硬件连接图形化配置485EN的配置串口的图形化配置 代码实现main.cgd32f3x0_hal_it.cgd32f3x0_hal_init.cgd32f3x0_hal_init.hgd32f3x0_hal_it.hgd32f3x0_libopt.h 备注END GD - Embe…...
英语中apartment(公寓)(美式)、house(房子)、flat(公寓)(英式)、villa(别墅)、room(房间)区别
文章目录 英语中apartment、house、flat、villa、room区别 英语中apartment、house、flat、villa、room区别 在英语中,“apartment”、“house”、“flat”、“villa”、和 “room” 这些词语都与居住空间有关,但它们各自的含义和用途有所不同ÿ…...
黑马头条vue2.0项目实战(十一)——功能优化(组件缓存、响应拦截器、路由跳转与权限管理)
1. 组件缓存 1.1 介绍 先来看一个问题? 从首页切换到我的,再从我的回到首页,我们发现首页重新渲染原来的状态没有了。 首先,这是正常的状态,并非问题,路由在切换的时候会销毁切出去的页面组件ÿ…...
《AI视频类工具之一—— 即创》
一.简介 官网:即创 - 一站式智能创意生产与管理平台 即创是字节跳动(现更名为抖音集团)旗下的一款一站式智能创意生产与管理平台,旨在帮助用户高效地进行创意内容的生成、管理和分析。 二.功能介绍 视频创作: 智能成片:利用AI技术自动编辑视频片段,快速生成完整的视频…...
CSS的:host伪类:精确定位于Web组件的指南
随着Web组件技术的发展,自定义元素(Custom Elements)已经成为现代Web开发中不可或缺的一部分。CSS的:host伪类为Web组件的样式封装提供了一种强大的工具,它允许开发者为自定义Web组件的宿主元素定义样式。本文将详细介绍:host伪类…...
安卓sdk manager下载安装
安卓sdk下载安装 android SDK manager下载 环境变量配置 ANDROID_HOME:D:\Android %ANDROID_HOME%\tools %ANDROID_HOME%\platform-tools %ANDROID_HOME%\build-tools\29.0.3Android SDK Platform-tools公用开发工具包,需要下载 Android SDK Tools基础…...
CV学习笔记3-图像特征提取
图像特征提取是计算机视觉中的一个关键步骤,其目标是从图像中提取有意义的特征,以便进行进一步的分析或任务,如分类、检测、分割等。特征提取可以帮助减少数据的维度,同时保留重要的信息。以下是常见的图像特征提取方法和技术&…...
Git使用方法(三)---简洁版上传git代码
1 默认已经装了sshWindows下安装SSH详细介绍-CSDN博客 2 配置链接github的SSH秘钥 1 我的.ssh路径 2 进入路径cd .ssh 文件 3 生成密钥对 ssh-keygen -t rsa -b 4096 (-t 秘钥类型 -b 生成大小) 输入完会出现 Enter file in which to save the key (/c/Users/Administrator/…...
8.21-部署eleme项目
1.设置主从从mysql57服务器 (1)配置主数据库 [rootmsater_5 ~]# systemctl stop firewalld[rootmsater_5 ~]# setenforce 0[rootmsater_5 ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.serv…...
多目标跟踪之ByteTrack论文(翻译+精读)
ByteTrack:通过关联每个检测框进行多对象跟踪 摘要 翻译 多对象跟踪(MOT)旨在估计视频中对象的边界框和身份。大多数方法通过关联分数高于阈值的检测框来获取身份。检测分数低的物体,例如被遮挡的物体被简单地丢弃,…...
【实践】Java开发常用工具类或中间件
在Java开发中,有许多常用的工具类和中间件,它们可以显著提高开发效率,简化代码,并提供强大的功能。这些工具类和中间件广泛应用于各种类型的Java应用程序中,包括Web应用、企业级应用、微服务等。以下是一些在Java开发中…...
Vue2移动端(H5项目)项目封装车牌选择组件
一、最终效果 二、参数配置 1、代码示例: <t-keyword:isShow"isShow"ok"isShowfalse"cancel"isShowfalse"inputchange"inputchange":finalValue"trailerNo"/>2、配置参数(TKeyword Attribute…...
四川财谷通信息技术有限公司抖音小店的优势
在数字化浪潮的推动下,电商行业迎来了前所未有的发展机遇,而抖音小店作为新兴的电商平台,凭借其独特的社交属性和便捷的购物体验,迅速赢得了广大消费者的青睐。在众多抖音小店中,四川财谷通信息技术有限公司旗下的抖音…...
2025届八股文:计算机网络高频重点面试题
鉴于排版复杂且篇幅过长,本文仅列举出问题,而未给出答案,有需要答案的同学可后台私信。整理总结不易,请尊重劳动成果,转载请注明出处。 目录 网络基础 HTTP TCP UDP IP PING WebSocket DNS 网络安全 网络基础…...
嵌入式和单片机有什么区别?
目录 (1)什么是嵌入式? (2)什么是单片机? (3)嵌入式和单片机的共同点 (4)嵌入式和单片机的区别 (1)什么是嵌入式? 关…...
JSON.stringify 和 JSON.parse
JSON.stringify 是一个将 JavaScript 对象转换为 JSON 字符串的方法,它有三个参数: JSON.stringify(value, replacer, space) 参数详解 value (必需): 这是你想要转换为 JSON 字符串的 JavaScript 对象或数组。例如:…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
