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 SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...