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

IO多路转接之select

IO多路转接之select

  • 1. IO多路转接(复用)
  • 2. select
    • 2.1 函数原型
    • 2.2 细节描述
  • 3. 并发处理
    • 3.1 处理流程
    • 3.2 通信代码

原文链接

1. IO多路转接(复用)

IO多路转接也称为IO多路复用,它是一种网络通信的手段(机制),通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的,一旦检测到有文件描述符就绪( 可以读数据或者可以写数据)程序的阻塞就会被解除,之后就可以基于这些(一个或多个)就绪的文件描述符进行通信了。通过这种方式在单线程/进程的场景下也可以在服务器端实现并发。常见的IO多路转接方式有:selectpollepoll

下面先对多线程/多进程并发和IO多路转接的并发处理流程进行对比(服务器端):

  • 多线程/多进程并发
    • 主线程/父进程:调用 accept()监测客户端连接请求
      • 如果没有新的客户端的连接请求,当前线程/进程会阻塞
      • 如果有新的客户端连接请求解除阻塞,建立连接
  • 子线程/子进程:和建立连接的客户端通信
    • 调用 read() / recv() 接收客户端发送的通信数据,如果没有通信数据,当前线程/进程会阻塞,数据到达之后阻塞自动解除
    • 调用 write() / send() 给客户端发送数据,如果写缓冲区已满,当前线程/进程会阻塞,否则将待发送数据写入写缓冲区中
  • IO多路转接并发
    • 使用IO多路转接函数委托内核检测服务器端所有的文件描述符(通信和监听两类),这个检测过程会导致进程/线程的阻塞,如果检测到已就绪的文件描述符阻塞解除,并将这些已就绪的文件描述符传出
    • 根据类型对传出的所有已就绪文件描述符进行判断,并做出不同的处理
      • 监听的文件描述符:和客户端建立连接
        • 此时调用accept()是不会导致程序阻塞的,因为监听的文件描述符是已就绪的(有新请求)
      • 通信的文件描述符:调用通信函数和已建立连接的客户端通信
        • 调用 read() / recv() 不会阻塞程序,因为通信的文件描述符是就绪的,读缓冲区内已有数据
        • 调用 write() / send() 不会阻塞程序,因为通信的文件描述符是就绪的,写缓冲区不满,可以往里面写数据
    • 对这些文件描述符继续进行下一轮的检测(循环往复。。。)

与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

2. select

2.1 函数原型

使用select这种IO多路转接方式需要调用一个同名函数select,这个函数是跨平台的,Linux、Mac、Windows都是支持的。程序猿通过调用这个函数可以委托内核帮助我们检测若干个文件描述符的状态,其实就是检测这些文件描述符对应的读写缓冲区的状态:

  • 读缓冲区:检测里边有没有数据,如果有数据该缓冲区对应的文件描述符就绪
  • 写缓冲区:检测写缓冲区是否可以写(有没有容量),如果有容量可以写,缓冲区对应的文件描述符就绪
  • 读写异常:检测读写缓冲区是否有异常,如果有该缓冲区对应的文件描述符就绪

委托检测的文件描述符被遍历检测完毕之后,已就绪的这些满足条件的文件描述符会通过select()的参数分3个集合传出,程序猿得到这几个集合之后就可以分情况依次处理了。

下面来看一下这个函数的函数原型:

#include <sys/select.h>
struct timeval {time_t      tv_sec;         /* seconds */suseconds_t tv_usec;        /* microseconds */
};int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval * timeout);
  • 函数参数:
    • nfds:委托内核检测的这三个集合中最大的文件描述符 + 1
      • 内核需要线性遍历这些集合中的文件描述符,这个值是循环结束的条件
      • 在Window中这个参数是无效的,指定为-1即可
    • readfds:文件描述符的集合, 内核只检测这个集合中文件描述符对应的读缓冲区
      • 传入传出参数,读集合一般情况下都是需要检测的,这样才知道通过哪个文件描述符接收数据
    • writefds:文件描述符的集合, 内核只检测这个集合中文件描述符对应的写缓冲区
      • 传入传出参数,如果不需要使用这个参数可以指定为NULL
    • exceptfds:文件描述符的集合, 内核检测集合中文件描述符是否有异常状态
      • 传入传出参数,如果不需要使用这个参数可以指定为NULL
    • timeout:超时时长,用来强制解除select()函数的阻塞的
      • NULL:函数检测不到就绪的文件描述符会一直阻塞。
      • 等待固定时长(秒):函数检测不到就绪的文件描述符,在指定时长之后强制解除阻塞,函数返回0
      • 不等待:函数不会阻塞,直接将该参数对应的结构体初始化为0即可。
  • 函数返回值:
    • 大于0:成功,返回集合中已就绪的文件描述符的总个数
    • 等于-1:函数调用失败
    • 等于0:超时,没有检测到就绪的文件描述符

另外初始化fd_set类型的参数还需要使用相关的一些列操作函数,具体如下:

// 将文件描述符fd从set集合中删除 == 将fd对应的标志位设置为0        
void FD_CLR(int fd, fd_set *set);
// 判断文件描述符fd是否在set集合中 == 读一下fd对应的标志位到底是0还是1
int  FD_ISSET(int fd, fd_set *set);
// 将文件描述符fd添加到set集合中 == 将fd对应的标志位设置为1
void FD_SET(int fd, fd_set *set);
// 将set集合中, 所有文件文件描述符对应的标志位设置为0, 集合中没有添加任何文件描述符
void FD_ZERO(fd_set *set);

2.2 细节描述

在select()函数中第2、3、4个参数都是fd_set类型,它表示一个文件描述符的集合,类似于信号集 sigset_t,这个类型的数据有128个字节,也就是1024个标志位,和内核中文件描述符表中的文件描述符个数是一样的。

sizeof(fd_set) = 128 字节 * 8 = 1024 bit      // int [32]

这并不是巧合,而是故意为之。这块内存中的每一个bit 和 文件描述符表中的每一个文件描述符是一一对应的关系,这样就可以使用最小的存储空间将要表达的意思描述出来了。

下图中的fd_set中存储了要委托内核检测读缓冲区的文件描述符集合。

  • 如果集合中的标志位为0代表不检测这个文件描述符状态
  • 如果集合中的标志位为1代表检测这个文件描述符状态

在这里插入图片描述

内核在遍历这个读集合的过程中,如果被检测的文件描述符对应的读缓冲区中没有数据,内核将修改这个文件描述符在读集合fd_set中对应的标志位,改为0,如果有数据那么这个标志位的值不变,还是1
在这里插入图片描述

select()函数解除阻塞之后,被内核修改过的读集合通过参数传出,此时集合中只要标志位的值为1,那么它对应的文件描述符肯定是就绪的,我们就可以基于这个文件描述符和客户端建立新连接或者通信了。

3. 并发处理

3.1 处理流程

如果在服务器基于select实现并发,其处理流程如下:

  1. 创建监听的套接字 lfd = socket();
  2. 将监听的套接字和本地的IP和端口绑定 bind()
  3. 给监听的套接字设置监听 listen()
  4. 创建一个文件描述符集合 fd_set,用于存储需要检测读事件的所有的文件描述符
    • 通过 FD_ZERO() 初始化
    • 通过 FD_SET() 将监听的文件描述符放入检测的读集合中
  5. 循环调用select(),周期性的对所有的文件描述符进行检测
  6. select() 解除阻塞返回,得到内核传出的满足条件的就绪的文件描述符集合
    • 通过FD_ISSET() 判断集合中的标志位是否为 1
      • 如果这个文件描述符是监听的文件描述符,调用 accept() 和客户端建立连接
        • 将得到的新的通信的文件描述符,通过FD_SET() 放入到检测集合中
      • 如果这个文件描述符是通信的文件描述符,调用通信函数和客户端通信
        • 如果客户端和服务器断开了连接,使用FD_CLR()将这个文件描述符从检测集合中删除
        • 如果没有断开连接,正常通信即可
  7. 重复第6步
    在这里插入图片描述

3.2 通信代码

select_server.cpp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main()
{// 1. 创建监听的fdint lfd = socket(AF_INET, SOCK_STREAM, 0);// 2. 绑定struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = INADDR_ANY;bind(lfd, (struct sockaddr*)&addr, sizeof(addr));// 3. 设置监听listen(lfd, 128);// 将监听的fd的状态检测委托给内核检测int maxfd = lfd;// 初始化检测的读集合fd_set rdset;fd_set rdtemp;// 清零FD_ZERO(&rdset);// 将监听的lfd设置到检测的读集合中FD_SET(lfd, &rdset);// 通过select委托内核检测读集合中的文件描述符状态, 检测read缓冲区有没有数据// 如果有数据, select解除阻塞返回// 应该让内核持续检测while(1){// 默认阻塞// rdset 中是委托内核检测的所有的文件描述符rdtemp = rdset;// 这里timeout参数一定要设置为结构体,要么就设为NULL,NULL就是默认阻塞struct timeval timeout;timeout.tv_sec = 0;timeout.tv_usec = 0;int num = select(maxfd+1, &rdtemp, NULL, NULL, &timeout);// rdset中的数据被内核改写了, 只保留了发生变化的文件描述的标志位上的1, 没变化的改为0// 只要rdset中的fd对应的标志位为1 -> 缓冲区有数据了// 判断有无新连接// 有新连接if(FD_ISSET(lfd, &rdtemp)){// 接受连接请求, 这个调用不阻塞struct sockaddr_in cliaddr;int cliLen = sizeof(cliaddr);int cfd = accept(lfd, (struct sockaddr*)&cliaddr, (socklen_t*)&cliLen);printf("%d\n",cfd);// 得到了有效的文件描述符// 通信的文件描述符添加到读集合// 在下一轮select检测的时候, 就能得到缓冲区的状态FD_SET(cfd, &rdset);// 重置最大的文件描述符maxfd = cfd > maxfd ? cfd : maxfd;}// 没有新连接, 通信for(int i=0; i<maxfd+1; ++i){// 判断从监听的文件描述符之后到maxfd这个范围内的文件描述符是否读缓冲区有数据,i != lfd 是因为 lfd是监听的socketif(i != lfd && FD_ISSET(i, &rdtemp)){// 接收数据char buf[10] = {0};// 一次只能接收10个字节, 客户端一次发送100个字节// 一次是接收不完的, 文件描述符对应的读缓冲区中还有数据// 下一轮select检测的时候, 内核还会标记这个文件描述符缓冲区有数据 -> 再读一次// 	循环会一直持续, 直到缓冲区数据被读完为止int len = read(i, buf, sizeof(buf));if(len == 0){printf("客户端关闭了连接...\n");// 将检测的文件描述符从读集合中删除FD_CLR(i, &rdset);close(i);}else if(len > 0){// 收到了数据// 发送数据write(i, buf, strlen(buf)+1);printf("读取了数据回传给客户端\n");}else{// 异常perror("read");}}}}return 0;
}

select_client.cpp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main()
{// 1. 创建用于通信的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd == -1){perror("socket");exit(0);}// 2. 连接服务器struct sockaddr_in addr;addr.sin_family = AF_INET;     // ipv4addr.sin_port = htons(9999);   // 服务器监听的端口, 字节序应该是网络字节序inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));if(ret == -1){perror("connect");exit(0);}// 通信while(1){// 读数据char recvBuf[1024];// 写数据// sprintf(recvBuf, "data: %d\n", i++);fgets(recvBuf, sizeof(recvBuf), stdin);write(fd, recvBuf, strlen(recvBuf)+1);// 如果客户端没有发送数据, 默认阻塞read(fd, recvBuf, sizeof(recvBuf));printf("recv buf: %s\n", recvBuf);sleep(1);}// 释放资源close(fd); return 0;
}

客户端不需要使用IO多路转接进行处理,因为客户端和服务器的对应关系是 1:N,也就是说客户端是比较专一的,只能和一个连接成功的服务器通信。

虽然使用select这种IO多路转接技术可以降低系统开销,提高程序效率,但是它也有局限性:

  1. 待检测集合(第2、3、4个参数)需要频繁的在用户区和内核区之间进行数据的拷贝,效率低
  2. 内核对于select传递进来的待检测集合的检测方式是线性的
    • 如果集合内待检测的文件描述符很多,检测效率会比较低
    • 如果集合内待检测的文件描述符相对较少,检测效率会比较高
  3. 使用select能够检测的最大文件描述符个数有上限,默认是1024,这是在内核中被写死了的。

自己的一点理解:

select里面的timeout参数一定要设置为结构体,要么就设为NULL,NULL就是默认阻塞

调试可以发现服务端怎么工作的,select循环,只有当有空闲文件描述符的时候,分逻辑,到底是连接还是通信的。如果是通信的,会记录是否读完了数据,如果读完了,内核会将文件描述符重新标记为0,除非重新写入数据。

但是上面的客户端代码有个问题,就是服务端多次写入的时候,客户端只能收到前面10个字节的数据,但是如果循环调用read,客户端read会阻塞,因为这里服务端是不会主动发送数据的,只是把客户端传过来的数据重新传回去。想一下怎么解决这个问题?

相关文章:

IO多路转接之select

IO多路转接之select 1. IO多路转接&#xff08;复用&#xff09;2. select2.1 函数原型2.2 细节描述 3. 并发处理3.1 处理流程3.2 通信代码 原文链接 1. IO多路转接&#xff08;复用&#xff09; IO多路转接也称为IO多路复用&#xff0c;它是一种网络通信的手段&#xff08;机…...

linux如何删除大文件的第一行(sed)

可以用sed命令实现&#xff1a; 删除文档的第一行 1. sed -i 1d <file>删除文档的最后一行 1. sed -i $d <file>在文档指定行中增加一行 # 示例如下&#xff1a; echo "1"; echo "2"; echo "4"; echo "5"; # 想要在echo…...

Navicat 技术指引 | 适用于 GaussDB 分布式的备份/还原功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…...

【广州华锐互动VRAR】VR戒毒科普宣传系统有效提高戒毒成功率

随着科技的不断发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已经逐渐渗透到各个领域&#xff0c;为人们的生活带来了前所未有的便利。在教育科普领域&#xff0c;VR技术的应用也日益广泛&#xff0c;本文将详细介绍广州华锐互动开发的VR戒毒科普宣传系统&#xff0…...

守护安全,六氟化硫气体泄漏报警装置校准服务

在电力工业中&#xff0c;六氟化硫&#xff08;SF6&#xff09;气体是一种重要的介质&#xff0c;它用作封闭式中、高压开关的灭弧和绝缘气体。六氟化硫气体的卓越性能实现了装置经济化、低维护化的操作。与普通装置相比&#xff0c;可以节省最多90&#xff05;的空间。 六氟化…...

概率测度理论方法(第 2 部分)

一、说明 欢迎回到这个三部曲的第二部分&#xff01;在第一部分中&#xff0c;我们为测度论概率奠定了基础。我们探索了测量和可测量空间的概念&#xff0c;并使用这些概念定义了概率空间。在本文中&#xff0c;我们使用测度论来理解随机变量。 作为一个小回顾&#xff0c;在第…...

实战:Docker Compose 下 Nginx、Java、Mysql 和 Redis 服务协同部署(包含解决浏览器访问Linux部署服务器本地资源问题)

1. 背景 在该实战中&#xff0c;我们将探讨如何使用Docker Compose协同部署Nginx、Java、Mysql和Redis服务&#xff0c;实现一个视频上传与展示的应用。具体需求如下&#xff1a; Java应用负责上传视频和图片资源到Nginx目录下&#xff0c;作为资源服务器。Nginx服务作为静态…...

Docker 设置国内镜像源

Docker 设置国内镜像源 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器 具体配置如下&#xff1a; {"registry-mirrors" : ["https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://docker.mirro…...

通信协议 远程调用RPC

1.通讯协议 所有的HDFS通讯协议都是建立在TCP/IP协议之上。 客户端通过一个可配置的TCP端口连接到Namenode&#xff0c;通过ClientProtocol协议与Namenode交 互。而Datanode使用DatanodeProtocol协议与Namenode交互。 一个远程过程调用(RPC)模型被抽象出来封装ClientProtoc…...

决策树 算法原理

决策树 算法原理 决策树的原理 决策树: 从训练数据中学习得出一个树状结构的模型 决策树属于判别模型 决策树是一种树状结构&#xff0c;通过做出一系列决策 (选择) 来对数据进行划分&#xff0c;这类似于针对一系列问题进行选择。 决策树的决策过程就是从根节点开始&#…...

Git全局设置命令---设置提交人邮箱

介绍 使用git命令设置提交人邮箱。 命令 git config --global user.email "xxxxxxxx.com"...

3DCAT+上汽奥迪:打造新零售汽车配置器实时云渲染解决方案

在 5G、云计算等技术飞速发展的加持下&#xff0c;云渲染技术迎来了突飞猛进的发展。在这样的背景下&#xff0c;3DCAT应运而生&#xff0c;成为了业内知名的实时云渲染服务商之一。 交互式3D实时云看车作为云渲染技术的一种使用场景&#xff0c;也逐步成为一种新的看车方式&a…...

物联网+AI智慧工地云平台源码(SaaS模式)

智慧工地云平台充分运用数字化技术&#xff0c;聚焦施工现场岗位一线&#xff0c;依托物联网、互联网、AI等技术&#xff0c;围绕施工现场管理的人、机、料、法、环五大维度&#xff0c;以及施工过程管理的进度、质量、安全三大体系为基础应用&#xff0c;实现全面高效的工程管…...

python打开相机,用鼠标左键框选矩形区域,支持一次框选多个矩形区域,通过鼠标右标清除上一次画的矩形。

方案一 import cv2# Global variables rectangles [] current_rectangle [] drawing False# Mouse callback function def mouse_callback(event, x, y, flags, param):global rectangles, current_rectangle, drawingif event cv2.EVENT_LBUTTONDOWN:drawing Truecurren…...

卷积之后通道数为什么变了

通道数增多与卷积之后得到的图像特征数量有关 卷积层的作用本来就是把输入中的特征分离出来变成新的 feature map&#xff0c;每一个输出通道就是一个卷积操作提取出来的一种特征。在此过程中ReLU激活起到过滤的作用&#xff0c;把负相关的特征点去掉&#xff0c;把正相关的留…...

ubuntu18.04安装opencv-4.5.5+opencv_contrib-4.5.5

一、安装opencv依赖 sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-d…...

实验3.5 路由器的单臂路由配置

实验3.5 路由器的单臂路由配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.SWA的基本配置2.RA的基本配置3.在RA上查看接口状态 六、任务验收七、任务小结 一、任务描述 某公司对部门划分了需VLAN之后&#xff0c;发现两个部门之间无法通信&#xff0c;但…...

nodejs微信小程序+python+PHP的基于大数据的家电销售分析系统设计与实现-计算机毕业设计推荐django

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…...

Windows server flask

1、Windows server 通过python的flask执行命令 from flask import Flask, request, abort import subprocess from flask_basicauth import BasicAuth app Flask(__name__) # 获取url是进行账号密码认证&#xff0c;设置url的账号密码 app.config[BASIC_AUTH_USERNAME] 账号…...

maven工程的pom.xml文件中增加了依赖,但偶尔没有下载到本地仓库

maven工程pom.xml文件中的个别依赖没有下载到本地maven仓库。以前没有遇到这种情况&#xff0c;今天就遇到了这个问题&#xff0c;把解决过程记录下来。 我在eclipse中编辑maven工程的pom.xml文件&#xff0c;增加对mybatis的依赖&#xff0c;但保存文件后&#xff0c;依赖的j…...

Navicat 技术指引 | 适用于 GaussDB 分布式的用户/权限功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…...

基于支持向量机SVM的新鲜度等级预测,基于自适应粒子群优化长短期神经网络的新鲜度等级预测

目录 背影 支持向量机SVM的详细原理 SVM的定义 SVM理论 粒子群算法原理 SVM应用实例,基于支持向量机SVM的新鲜度等级预测,基于自适应粒子群优化长短期神经网络的新鲜度等级预测 代码 结果分析 展望 完整代码:基于支持向量机SVM的新鲜度等级预测,基于自适应粒子群优化长短期…...

麒麟系统系统添加路由

系统添加路由 一、路由的解释&#xff1a; 路由工作在OSI参考模型第三层——网络层的数据包转发设备&#xff08;TCP/IP&#xff09;路由器根据收到数据包中的网络层地址以及路由器内部维护的路由表决定输出端口以及下一跳地址&#xff0c;并且重写链路层数据包头实现转发数据…...

考研真题数据结构

【2021年山西大学真题】将二叉树中所有非终端结点的左右子树交换位置&#xff0c;可以得到原二叉树的 镜像二叉树&#xff0c;如图。假设二叉树的存储形式为&#xff08;lchild&#xff0c;data&#xff0c;rchild&#xff09;&#xff0c;给出求镜像二叉树的算法: &#xff0…...

python爬取 HTTP_2 网站超时问题的解决方案

问题背景 在进行网络数据爬取时&#xff0c;使用 Python 程序访问支持 HTTP/2 协议的网站时&#xff0c;有时会遇到超时问题。这可能会导致数据获取不完整&#xff0c;影响爬虫程序的正常运行。 问题描述 在实际操作中&#xff0c;当使用 Python 编写的爬虫程序访问支持 HTT…...

学会用bash在linux写脚本 (二)

接着上一章继续 数值的对比 判断语句 循环语句 22.5 比较、对比、判断 在写脚本时&#xff0c;有时需要做一些比较&#xff0c;例如&#xff0c;两个数字谁大谁小&#xff0c;两个字符串是否相同等。 做对比的表达式有[]、[[]]、test&#xff0c;其中[]和 test这两种表达式的…...

QML中Dialog获取close与open状态

1.新建MyDialog.qml import QtQuick 2.15import QtQuick.Dialogs 1.2Dialog {id: rootvisible: falsetitle: qsTr("弹出对话框")width: 250height: 200} 2.main.qml中调用MyDialog import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15…...

用C语言实现队列的顺序结构

用C语言实现队列的初始化、队列的判空操作、入队操作、出队运算、取队头元素运算、顺序打印队列。 #include<stdio.h> #define QueueSize 100 typedef char ElemType; typedef struct//队列结构体 {ElemType data[QueueSize];//保存队中元素int front, rear;//队头和队尾…...

Vue 子路由页面发消息给主路由页面 ,实现主页面显示子页面的信息

需求 子页面进入后&#xff0c;能在主页面显示子页的相关信息&#xff0c;比如说主页面的菜单激活的是哪个子页面的菜单项 如上图&#xff0c;当刷新浏览器页面时&#xff0c;让菜单的激活项仍保持在【最近浏览】。 实现方式&#xff1a; 在子页面的create事件中增加&#xff…...

AR技术详解

1.AR技术平台 1.手机端 2.AR眼镜端 3.WebAR。 2.AR基础技术应用 1.平面检测技术 2.模型识别技术 3.图片识别技术 4.AR云&#xff08;云锚点&#xff09;技术 5.人脸检测技术 3.主要AR技术SDK 1.苹果ARKit&#xff0c;谷歌ARCore。 优点&#xff1a;推荐使用Unity开发&#xf…...

h5或uniapp或微信小程序,实现左上角返回到指定页面,侧滑左滑返回指定页面,安卓物理返回键返沪指定页面解决思路的思考

h5或uniapp或微信小程序&#xff0c;实现左上角返回到指定页面&#xff0c;侧滑左滑返回指定页面&#xff0c;安卓物理返回键返沪指定页面 uniapp开发app,(非微信小程序)uniapp写的微信小程序 uniapp开发app,(非微信小程序) 自定义的左上角返回按钮 <i class"iconfon…...

轻量封装WebGPU渲染系统示例<43>- PBR材质与阴影实(源码)

原理简介: 1. 基于rendering pass graph实现。 2. WGSL Shader 基于文件系统和宏机制动态组装。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PBRShadowTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&a…...

macOS Big Sur/Mac电脑安装vscode显示您没有权限来打开应用程序‘Visual Studio Code‘ 请联系您的电脑或网络管理员问题修复

错误方法 首先我以为我的权限不足。&#xff0c;需要去用户群组里设置。结果根本不是这个的问题。 1.在系统偏好设置->用户与群组检查了一下我的用户是不是管理员 结果发现是管理员 2.根据苹果提示&#xff0c;右键我的文件夹->显示简介->最下面的共享与权限 解锁&…...

jsp 如何批量改随机人名

对比图 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <%page import"java.sql.ResultSet"%> <%page import"java.sql.PreparedStatement"%> <%page import&qu…...

android项目实战之编辑器集成

引言 项目需要用到编辑器&#xff0c;采用RichEditor&#xff0c;如下效果 实现 1. 引入库2 implementation jp.wasabeef:richeditor-android:2.0.0 2. XML <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width&q…...

JAVA程序如何打jar和war问题解决

背景: 近期研究一个代码审计工具 需要jar包 jar太多了 可以将jar 打成war包 首先看下程序目录结构 pom.xml文件内容 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"ht…...

Microsoft 365 Copilot正式上线,如何稳定访问体验?

如果将微软对人工智能的投资看成一场豪赌&#xff0c;Microsoft Copilot无疑是现阶段最受瞩目的赌注。2023年9月正式发布的Microsoft Copilot是一种基于大型语言模型&#xff08;LLM&#xff09;和微软图形&#xff08;Microsoft Graph&#xff09;的数据和人工智能&#xff08…...

【安卓】安卓xTS之Media模块 学习笔记(3) VTS测试

1. 背景 接下来进行正式的VTS测试。本章节还是以Media模块相关进行介绍。 VTS主要测的是内核和HAL层&#xff0c;media的hal层是以openMax&#xff08;即将废弃&#xff0c;今日2023.12&#xff09; 和 Codec2 (后续主流) 接口为主。 这里我们只看Codec2的要求&#xff0c;CDD…...

Go实现http同步文件操作 - 增删改查

http同步文件操作 - 增删改查 http同步文件操作 - 增删改查1. 前置要求1.1. 构建结构体 文件名 文件内容1.1.1. 页面结构体1.1.2. 为Page结构体绑定方法&#xff1a;Save1.1.3. 对Page结构体支持页面内容查看方法&#xff0c;同时提供页面文件是否存在的方法 1.2. 简单验证上面…...

Spring Boot整合 Spring Security

Spring Boot整合 1、RBAC 权限模型 RBAC模型&#xff08;Role-Based Access Control&#xff1a;基于角色的访问控制&#xff09; 在RBAC模型里面&#xff0c;有3个基础组成部分&#xff0c;分别是&#xff1a;用户、角色和权限&#xff0c;它们之间的关系如下图所示 SELECT…...

浅谈低代码

低代码开发是近年来迅速崛起的软件开发方法&#xff0c;让编写应用程序变得更快、更简单。有人说它是美味的膳食&#xff0c;让开发过程高效而满足&#xff0c;但也有人质疑它是垃圾食品&#xff0c;缺乏定制性与深度。你认为低代码到底是美以下方向仅供参考。味的膳食还是垃圾…...

Innodb-ruby深入探索Innodb存储结构

达在之前已经分享过Innodb数据存储结构知识&#xff0c;但是都是基于理论原理知识理解&#xff0c;今天利用Innodb文件解析工具ruby进行探索Innodb真实的存储结构。 索引原理过程&#xff1a;【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引_innodb的聚集索引的数据插入_Surviv…...

Echarts的使用 笔记

1.数据可视化前言 1.1.什么是数据可视化 数据可视化&#xff1a; 就是把数据以更加直观的方式进行呈现. 1.2.数据可视化的好处 清晰有效地传达与沟通信息更容易洞察隐藏在数据中的信息 2.ECharts的基本使用 2.1.ECharts官网 ECharts是百度公司开源的一个使用 JavaScript 实…...

信息系统工程的基本概念

系统是由相互作用和相互依赖的若干部分&#xff0c;按一定规律结合成的、具有特定功能的有机整体。系统有下述特性&#xff1a; &#xff08;1&#xff09;集合性。系统是由许多元素有机地组成的整体。每个元素服从整体&#xff0c;追求全局最优。 &#xff08;2&#xff09;相…...

SAP UI5 walkthrough step10 Descriptor for Applications

在这一步&#xff0c;我们将会把所有的应用相关的描述性的文件独立放到manifest.json 新建一个manifest.json文件 webapp/manifest.json (New) {"_version": "1.58.0","sap.app": {"id": "ui5.walkthrough","i18n&q…...

打造专属小程序,乔拓云模板平台助力商家抢占先机

打造专属小程序&#xff0c;乔拓云模板平台助力商家抢占先机&#xff01;该平台涵盖全行业小程序模板&#xff0c;一键复制即可上线。 想要快速创建高效实用的小程序&#xff0c;乔拓云小程序模板开发平台为您提供了解决方案&#xff01;我们为您提供一系列精心设计的小程序模板…...

Vue2学习(组件的使用)

Vue中使用组件的三个步骤&#xff1a; 一、定义组件(或者叫创建组件) 使用Vue.extend(options)创建&#xff0c;其中options和new Vue(options)时传入的那个options几乎一样&#xff0c;但也有点区别&#xff1b; 区别如下&#xff1a; 1.el不要写&#xff0c;为什么&#x…...

基于Spring、SpringMVC、MyBatis开发的游乐场管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring、SpringMVC、MyBatis开发的游…...

数据清洗、特征工程和数据可视化、数据挖掘与建模的应用场景

1.5 数据清洗、特征工程和数据可视化、挖掘建模的应用场景 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.5节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应…...

Qt简介、工程文件分离、创建Qt工程、Qt的帮助文档

QT 简介 core&#xff1a;核心模块&#xff0c;非图形的接口类&#xff0c;为其它模块提供支持 gui&#xff1a;图形用户接口&#xff0c;qt5之前 widgets&#xff1a;图形界面相关的类模块 qt5之后的 database&#xff1a;数据库模块 network&#xff1a;网络模块 QT 特性 开…...