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

linux并发服务器 —— IO多路复用(八)

半关闭、端口复用

半关闭只能实现数据单方向的传输;当TCP 接中A向 B 发送 FIN 请求关闭,另一端 B 回应ACK 之后 (A 端进入 FIN_WAIT_2 状态),并没有立即发送 FIN 给 A,A 方处于半连接状态 (半开关),此时 A 可以接收 B 发送的数据,但是 A 已经不能再向 B 发送数据

close不会影响到其他进程,shutdown会影响到其他进程;

网络信息相关的命令

netstat

        -a 所有的Socket

        -p 正在所用socket的程序名称

        -n 直接使用IP地址,不通过域名服务器

端口复用

1. 防止服务器重启时之前绑定的端口还没释放

2. 程序突然退出而系统没有释放端口

IO多路复用简介

I/O多路复用使程序可以同时监听多个文件描述符,提高程序性能;select/poll/epoll

阻塞等待:不占用CPU宝贵时间;但同一时刻只能处理一个操作,效率低。

非阻塞,忙轮询:提高了程序执行效率;但会占用更多的CPU资源。

select/poll:委托内核进行检测,但仍需要进行遍历

epoll:同样委托内核,但无需进行遍历

select

主旨思想:

1. 构造关于文件描述符的列表,将要监听的文件描述符添加到表中

2. 调用系统函数,监听该列表中的文件描述符,知道描述符中的一个/多个进行了I/O操作,函数才返回(该函数是阻塞的,且该函数对于文件描述符的检测是由内核完成的)

3. 返回时,告诉进程有多少描述符要进行I/O操作

返回值: 失败 - -1,成功 - 检测到的描述符个数

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/select.h>
#include  <unistd.h>using namespace std;int main(){// 创建socketint lfd = socket(PF_INET , SOCK_STREAM , 0);struct sockaddr_in saddr;saddr.sin_port = htons(9999);saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = INADDR_ANY;// 绑定bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));// 监听listen(lfd , 8);fd_set rdset , tmp;FD_ZERO(&rdset);FD_SET(lfd , &rdset);int maxfd = lfd+1;while(1){tmp = rdset;// 调用select 系统检测int ret = select(maxfd+1 , &tmp , NULL , NULL , NULL);if(ret == -1){perror("select");exit(-1);}else if(ret == 0){continue;}else{// 检测到了文件描述符的数据发生了改变if(FD_ISSET(lfd , &tmp)){// 有客户端连接进来struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);// 添加进去FD_SET(cfd , &rdset);maxfd = maxfd>cfd?maxfd:cfd+1;}for(int i = lfd+1 ; i <= maxfd ; i++){if(FD_ISSET(i , &tmp)){// 说明客户端发来了数据char buf[1024];int len = read(i , buf , sizeof(buf));if(len == -1){perror("read");exit(-1);}else if(len == 0){cout<<"client close..."<<endl;close(i);FD_CLR(i,&rdset);}else{cout<<"发来了数据:"<<buf<<endl;write(i , buf , strlen(buf)+1);}}}}}close(lfd);return 0;
}

poll

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <poll.h>
#include  <unistd.h>using namespace std;int main(){// 创建socketint lfd = socket(PF_INET , SOCK_STREAM , 0);struct sockaddr_in saddr;saddr.sin_port = htons(9999);saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = INADDR_ANY;// 绑定bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));// 监听listen(lfd , 8);// 初始化检测文件描述符数组struct pollfd fds[1024];for(int i = 0 ; i<1024 ; i++){fds[i].fd = -1;fds[i].events = POLLIN;}fds[0].fd = lfd;int nfds = 0;while(1){// poll 系统检测int ret = poll(fds , nfds+1 , -1);if(ret == -1){perror("poll");exit(-1);}else if(ret == 0){continue;}else{// 检测到了文件描述符的数据发生了改变if(fds[0].revents & POLLIN){// 有客户端连接进来struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);// 添加进去for(int i = 1 ; i < 1024 ; i++){if(fds[i].fd == -1){fds[i].fd = cfd;fds[i].events = POLLIN;break;}}nfds = nfds>cfd?nfds:cfd;}for(int i = 1 ; i <= nfds ; i++){if(fds[i].revents & POLLIN){// 说明客户端发来了数据char buf[1024];int len = read(fds[i].fd , buf , sizeof(buf));if(len == -1){perror("read");exit(-1);}else if(len == 0){cout<<"client close..."<<endl;close(fds[i].fd);fds[i].fd = -1;}else{cout<<"发来了数据:"<<buf<<endl;write(fds[i].fd , buf , strlen(buf)+1);}}}}}close(lfd);return 0;
}

epoll

内核,红黑树记录要检测的文件描述符,避免了用户态到内核态的数据拷贝开销;

内核,双链表存放数据改变的文件描述符

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/epoll.h>
#include  <unistd.h>using namespace std;int main(){// 创建socketint lfd = socket(PF_INET , SOCK_STREAM , 0);struct sockaddr_in saddr;saddr.sin_port = htons(9999);saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = INADDR_ANY;// 绑定bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));// 监听listen(lfd , 8);// 创建epoll实例int epfd = epoll_create(100);// 添加监听文件描述符struct epoll_event epev;epev.events = EPOLLIN;epev.data.fd = lfd;epoll_ctl(epfd , EPOLL_CTL_ADD , lfd , &epev);struct epoll_event epevs[1024];while(1){int ret = epoll_wait(epfd , epevs , 1024 , -1);if(ret == -1){perror("epoll");exit(-1);}cout<<ret<<"个发生了改变"<<endl;for(int i = 0 ; i<ret ; i++){int curfd = epevs[i].data.fd;if(curfd == lfd){// 监听的文件描述符有客户端连接struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);epev.events = EPOLLIN;epev.data.fd = cfd;epoll_ctl(epfd , EPOLL_CTL_ADD , cfd , &epev);}else{// 有数据到达char buf[1024];int len = read(curfd , buf , sizeof(buf));if(len == -1){perror("read");exit(-1);}else if(len == 0){cout<<"client close..."<<endl;epoll_ctl(epfd , EPOLL_CTL_DEL , curfd , NULL);close(curfd);}else{cout<<"发来了数据:"<<buf<<endl;write(curfd , buf , strlen(buf)+1);}}}}close(lfd);close(epfd);return 0;
}

epoll的两种工作模式

LT模式 - 水平触发

默认的工作模式,支持block/no-block;,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的 fd 进行IO操作。如果你不作任何操作,内核还是会继续通知你

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/epoll.h>
#include  <unistd.h>using namespace std;int main(){// 创建socketint lfd = socket(PF_INET , SOCK_STREAM , 0);struct sockaddr_in saddr;saddr.sin_port = htons(9999);saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = INADDR_ANY;// 绑定bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));// 监听listen(lfd , 8);// 创建epoll实例int epfd = epoll_create(100);// 添加监听文件描述符struct epoll_event epev;epev.events = EPOLLIN;epev.data.fd = lfd;epoll_ctl(epfd , EPOLL_CTL_ADD , lfd , &epev);struct epoll_event epevs[1024];while(1){int ret = epoll_wait(epfd , epevs , 1024 , -1);if(ret == -1){perror("epoll");exit(-1);}cout<<ret<<"个发生了改变"<<endl;for(int i = 0 ; i<ret ; i++){int curfd = epevs[i].data.fd;if(curfd == lfd){// 监听的文件描述符有客户端连接struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);epev.events = EPOLLIN;epev.data.fd = cfd;epoll_ctl(epfd , EPOLL_CTL_ADD , cfd , &epev);}else{// 有数据到达char buf[5];int len = read(curfd , buf , sizeof(buf));if(len == -1){perror("read");exit(-1);}else if(len == 0){cout<<"client close..."<<endl;epoll_ctl(epfd , EPOLL_CTL_DEL , curfd , NULL);close(curfd);}else{cout<<"发来了数据:"<<buf<<endl;write(curfd , buf , strlen(buf)+1);}}}}close(lfd);close(epfd);return 0;
}

ET模式 - 边沿触发

告诉工作方式,只支持no-block,在这种模式下,当描述符从未就绪变为就绪时,内核通过epol告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了。但是请注意如果一直不对这个 fd 作IO操作,内核不会发送更多的通知 (only once) 。但是缓冲区中的数据不会丢失

ET模式效率比LT模式高,ET模式下必须使用非阻塞套接口,避免由于一个描述符的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死;

要设置边沿触发

1. 需要在epoll_event中设置EPOLLET

2. 

UDP通信实现 - 无需多进程/多线程的并发实现

// server
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using namespace std;int main(){// 创建socketint fd = socket(PF_INET , SOCK_DGRAM , 0);if(fd == -1){perror("socket");exit(-1);}// 绑定struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = INADDR_ANY;int ret = bind(fd ,(struct sockaddr*) &addr , sizeof(addr));if(ret == -1){perror("bind");exit(-1);}// 通信while(1){// 接收数据char buf[128];char ip[16];struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int num = recvfrom(fd , buf , sizeof(buf) , 0 , (struct sockaddr*)&caddr , &len);string s1 = "IP: ";s1 += inet_ntop(AF_INET , &caddr.sin_addr.s_addr , ip , sizeof(ip));string s2 = "Port: ";s2 += ntohs(caddr.sin_port);cout<<s1<<" "<<s2<<endl;cout<<"rcv data: "<<buf<<endl;sendto(fd , buf , strlen(buf)+1 , 0 , (struct sockaddr*)&caddr , len);}close(fd);return 0;
}
// client
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using namespace std;int main(){// 创建socketint fd = socket(PF_INET , SOCK_DGRAM , 0);if(fd == -1){perror("socket");exit(-1);}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);inet_pton(AF_INET , "127.0.0.1" , &addr.sin_addr.s_addr);// 通信int num = 0;socklen_t len = sizeof(addr);while(1){char buf[128];sprintf(buf , "hello 647 %d" , num++);sendto(fd , buf , strlen(buf)+1 , 0 , (struct sockaddr*)&addr , len);// 接收数据int num = recvfrom(fd , buf , sizeof(buf) , 0 , NULL , NULL);cout<<"rcv data: "<<buf<<endl;sleep(1);}close(fd);return 0;
}

广播和组播 - 只能使用UDP

广播 - 向子网中多台计算机发送消息,每个广播消息都包含一个特殊的IP地址,这个IP中子网内主机标志部分的二进制全部为1;

1. 只能在局域网中使用

2. 客户端需要绑定服务器广播使用的端口,才能接收到广播消息

组播 (多播) - 标识一组IP接口,是在单播和广播之间的一种折中方案,多播数据包只由对其感兴趣的接口接收;

1. 组播可以用于局域网和广域网

2. 客户端需要加入多播组才能接收到

本地套接字通信

作用:用于进程间的通信;实现流程和网络套接字类似,一般采用TCP的通信流程

服务器端1. 创建监听的套接字int lfd = socket(AF_UNIX/AF_LOCAL , SOCK_STREAM , 0);2. 监听套接字绑定本地的套接字文件struct sockaddr_un addr;bind(lfd, addr, len); // 绑定成功后sun_path中的套接字文件会自动生成3. 监听4. 等待并接受客户端请求5. 通信6. 关闭连接
客户端1. 创建通信的套接字2. 绑定本地IP端口3. 连接服务器4. 通信5. 关闭连接
// 服务端
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
using namespace std;int main(){unlink("server.sock");// 创建监听套接字int lfd = socket(AF_LOCAL , SOCK_STREAM , 0);if(lfd == -1){perror("socket");exit(-1);}// 绑定本地套接字文件struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy(addr.sun_path , "server.sock");int ret = bind(lfd , (struct sockaddr*)&addr , sizeof(addr));if(ret == -1){perror("bind");exit(-1);}// 监听ret = listen(lfd , 100);if(ret == -1){perror("listen");exit(-1);}// 等待客户端连接struct sockaddr_un caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);if(cfd == -1){perror("accept");exit(-1);}cout<<"客户端文件:"<<caddr.sun_path<<endl;// 通信while(1){char buf[128];int len = recv(cfd , buf , sizeof(buf) , 0);if(len ==  -1){perror("recv");exit(-1);}else if(len == 0){cout<<"client close..."<<endl;break;}else{cout<<"recv data: "<<buf<<endl;send(cfd , buf , len , 0);}}close(cfd);close(lfd);return 0;
}
// 客户端
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
using namespace std;int main(){unlink("client.sock");// 创建监听套接字int cfd = socket(AF_LOCAL , SOCK_STREAM , 0);if(cfd == -1){perror("socket");exit(-1);}// 绑定本地套接字文件struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy(addr.sun_path , "client.sock");int ret = bind(cfd , (struct sockaddr*)&addr , sizeof(addr));if(ret == -1){perror("bind");exit(-1);}// 连接服务器struct sockaddr_un saddr;saddr.sun_family = AF_LOCAL;strcpy(saddr.sun_path , "server.sock");ret = connect(cfd , (struct sockaddr*)&saddr , sizeof(saddr));if(ret == -1){perror("connect");exit(-1);}// 通信int num = 0;while(1){char buf[128];sprintf(buf , "hello 647 %d\n" , num++);send(cfd , buf , strlen(buf)+1 , 0);int len = recv(cfd , buf , sizeof(buf) , 0);if(len ==  -1){perror("recv");exit(-1);}else if(len == 0){cout<<"Server close..."<<endl;break;}else{cout<<"recv data: "<<buf<<endl;}sleep(1);}close(cfd);return 0;
}

相关文章:

linux并发服务器 —— IO多路复用(八)

半关闭、端口复用 半关闭只能实现数据单方向的传输&#xff1b;当TCP 接中A向 B 发送 FIN 请求关闭&#xff0c;另一端 B 回应ACK 之后 (A 端进入 FIN_WAIT_2 状态)&#xff0c;并没有立即发送 FIN 给 A&#xff0c;A 方处于半连接状态 (半开关)&#xff0c;此时 A 可以接收 B…...

企微SCRM营销平台MarketGo-ChatGPT助力私域运营

一、前言 ChatGPT是由OpenAI&#xff08;开放人工智能&#xff09;研发的自然语言处理模型&#xff0c;其全称为"Conversational Generative Pre-trained Transformer"&#xff0c;即对话式预训练转换器。它是GPT系列模型的最新版本&#xff0c;GPT全称为"Gene…...

linux C++ 海康截图Demo

项目结构 CMakeLists.txt cmake_minimum_required(VERSION 3.7)project(CapPictureTest)include_directories(include)link_directories(${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/lib/HCNetSDKCom) add_executable(CapPictureTest ${CMAKE_SOURCE_DIR}/src/CapPictureTes…...

MySQL的事务隔离级别

目录 事务隔离级别的概念 脏读&#xff08;Dirty Read&#xff09;&#xff1a; 不可重复读&#xff08;Non-Repeatable Read&#xff09;&#xff1a; 幻读&#xff08;Phantom Read&#xff09;&#xff1a; 读未提交&#xff08;Read Uncommitted&#xff09; 读未提交…...

企业大语言模型智能问答的底层基础数据知识库如何搭建?

企业大语言模型智能问答的底层基础数据知识库搭建是一个复杂而关键的过程。下面将详细介绍如何搭建这样一个知识库。 确定知识库的范围和目标&#xff1a; 首先&#xff0c;需要明确知识库的范围&#xff0c;确定所涵盖的领域和主题。这可以根据企业的业务领域和用户需求来确…...

【腾讯云 Cloud Studio 实战训练营】使用python爬虫和数据可视化对比“泸州老窖和五粮液4年内股票变化”

Cloud Studio 简介 Cloud Studio是腾讯云发布的云端开发者工具&#xff0c;支持开发者利用Web IDE&#xff08;集成开发环境&#xff09;&#xff0c;实现远程协作开发和应用部署。 现在的Cloud Studio已经全面支持Java Spring Boot、Python、Node.js等多种开发模板示例库&am…...

Linux之Shell概述

目录 Linux之Shell概述 学习shell的原因 shell是什么 shell起源 查看当前系统支持的shell 查看当前系统默认shell Shell 概念 Shell 程序设计语言 Shell 也是一种脚本语言 用途 Shell脚本的基本元素 基本元素构成&#xff1a; Shell脚本中的注释和风格 Shell脚本编…...

手写Spring:第2章-创建简单的Bean容器

文章目录 一、目标&#xff1a;创建简单的Bean容器二、设计&#xff1a;创建简单的Bean容器三、实现&#xff1a;创建简单的Bean容器3.0 引入依赖3.1 工程结构3.2 创建简单Bean容器类图3.3 Bean定义3.4 Bean工厂 四、测试&#xff1a;创建简单的Bean容器4.1 用户Bean对象4.2 单…...

在Windows上通过SSH公私钥实现无密码登录Linux

在Windows上通过SSH公私钥实现无密码登录Linux 在Windows上生成SSH密钥对&#xff1a; 打开命令提示符或PowerShell窗口。 输入以下命令生成SSH密钥对&#xff1a; ssh-keygen -t rsa -b 4096按照提示输入密钥的保存路径和密码&#xff08;可选&#xff09;。 在指定的路径下…...

使用ppt和texlive生成eps图片(高清、可插入latex论文)

一、说明 写论文经常需要生成高清的图片插入到论文中&#xff0c;本文以ppt画图生成高质量的eps图片的实现来介绍具体操作方法。关于为什么要生成eps图片&#xff0c;一个是期刊要求&#xff08;也有不要求的&#xff09;&#xff0c;另一个是显示图像的质量高。 转化获得eps…...

html5学习笔记19-SSE服务器发送事件(Server-Sent Events)

https://www.runoob.com/html/html5-serversentevents.html 允许网页获得来自服务器的更新。类似设置回调函数。 if(typeof(EventSource)!"undefined"){var sourcenew EventSource("demo_sse.php");source.onmessagefunction(event){document.getElement…...

高效数据湖构建与数据仓库融合:大规模数据架构最佳实践

文章目录 数据湖和数据仓库&#xff1a;两大不同理念数据湖数据仓库 数据湖与数据仓库的融合统一数据目录数据清洗和转换数据安全和权限控制数据分析和可视化 数据湖与数据仓库融合的优势未来趋势云原生数据湖自动化数据处理边缘计算与数据湖融合 结论 &#x1f389;欢迎来到云…...

Java学习笔记——35多线程02

线程同步 线程同步卖票案例同步代码块同步方法块 线程安全的类StringBufferVectorHashtable Lock锁 线程同步 卖票案例 public class SellTicket implements Runnable{private int tickets10;Overridepublic void run(){while (true){if(tickets>0){System.out.println(Th…...

每日刷题-3

目录 一、选择题 二、编程题 1、计算糖果 2、进制转换 一、选择题 1、 解析&#xff1a;在C语言中&#xff0c;以0开头的整数常量是八进制的&#xff0c;而不是十进制的。所以&#xff0c;0123的八进制表示相当于83的十进制表示&#xff0c;而123的十进制表示不变。printf函数…...

储能直流侧计量表DJSF1352

安科瑞 华楠 具有CE/UL/CPA/TUV认证 DJSF1352-RN导轨式直流电能表带有双路直流输入&#xff0c;主要针对电信基站、直流充电桩、太阳能光伏等应用场合而设计&#xff0c;该系列仪表可测量直流系统中的电压、电流、功率以及正反向电能等。在实际使用现场&#xff0c;即可计量总…...

机器学习报错合集(持续更新)

文章目录 1 列表转numpy&#xff0c;尺寸不均匀问题 1 列表转numpy&#xff0c;尺寸不均匀问题 ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (4,) inhomogeneous pa…...

【android12-linux-5.1】【ST芯片】【RK3588】【LSM6DSR】驱动移植

一、环境介绍 RK3588主板搭载Android12操作系统,内核是Linux5.10,使用ST的六轴传感器LSM6DSR芯片。 二、芯片介绍 LSM6DSR是一款加速度和角速度(陀螺仪)六轴传感器,还内置了一个温度传感器。该芯片可以选择I2C,SPI通讯,还有可编程终端,可以后置摄像头等设备,功能是很…...

day-41 代码随想录算法训练营(19)动态规划 part 03

343.整数拆分 思路&#xff1a; 1.dp存储的是第i个数&#xff0c;拆分之后最大乘积2.dp[i]max(dp[i],max(j*(i-j),j*dp[i-j]));3.初始化&#xff1a;dp[0]dp[1]0,dp[2]1;4.遍历顺序&#xff1a;外层循环 3-n&#xff0c;内层循环 1-i 2.涉及两次取max&#xff1a; dp[i] 表…...

K8S安装部署 初始化操作(一)

准备好服务器和服务器资源 ip hostnameip资源 &#xff08;2核2G也可以&#xff09;k8s-master 192.168.37.1184核 4G 40G硬盘k8s-node1192.168.37.1192核 2G 20G硬盘k8s-node2192.168.37.1202核 2G 20G硬盘 初始操作三台同时执行 1、关闭防火墙 [rootlocalhost ~]# s…...

【多线程案例】单例模式(懒汉模式和饿汉模式)

文章目录 1. 什么是单例模式&#xff1f;2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式&#xff1f; 提起单例模式&#xff0c;就必须介绍设计模式&#xff0c;而设计模式就是在软件设计中&#xff0c;针对特殊…...

利用COMSOL软件对变压器局部放电超声波传播特性进行了有限元声学仿真,首先建立包括变压器油、...

利用COMSOL软件对变压器局部放电超声波传播特性进行了有限元声学仿真&#xff0c;首先建立包括变压器油、铁芯、绕组和基座的变压器几何模型&#xff0c;选取符合声压波动方程的压力声学物理场&#xff0c;建立了局放超声波声源模型&#xff0c;可用于研究固定声源的声压时间和…...

HOOI算法里的‘skip’参数到底在干嘛?深入TensorLy源码讲透Tucker分解迭代过程

HOOI算法中的skip参数机制解析&#xff1a;从数学原理到TensorLy实现 当你在实现高阶正交迭代&#xff08;HOOI&#xff09;算法进行Tucker分解时&#xff0c;是否曾被multi_mode_dot函数中那个神秘的skip参数困扰过&#xff1f;这个看似简单的参数背后&#xff0c;实际上隐藏着…...

手把手教你用DrissionPage搭建个人新闻聚合器:自动抓取百度热搜并保存到Excel

用DrissionPage打造智能新闻聚合器&#xff1a;从百度热搜抓取到Excel自动化分析 每天手动刷新闻不仅耗时&#xff0c;还容易错过重要信息。想象一下&#xff0c;如果有个私人助手能自动收集全网热点&#xff0c;整理成结构化的报告&#xff0c;甚至生成直观的可视化图表——这…...

微信小程序自动化测试:自定义测试(Minium)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快录制回放支持输入&#xff0c;文本查找&#xff0c;断言等自动化测试基础操作&#xff0c;无需编写代码&#xff0c;用例生成效率高&#xff0c;但是部分操作不支持…...

扩散浓度曲线计算:从实例看 Pandat 代算与自行操作

扩散浓度曲线计算(Pandat代算或自己操作) 实例33: Al-4.06at%Mg/Al扩散偶在781K下退火36960s&#xff0c;Mg元素浓度随距离的变化曲线及实验数据对比如图a所示&#xff1b;Al-11at%Mg/Al扩散偶在773K下退火86400s&#xff0c;Mg元素浓度随距离的变化曲线及实验对比如图b所示&am…...

嵌入式SD卡文件处理轻量级工具库LC_SDTools

1. LC_SDTools 库概述LC_SDTools 是一个面向嵌入式 SD 卡文件系统应用的轻量级工具库&#xff0c;专为解决裸机或 RTOS 环境下 SD 卡文件操作中高频缺失的基础能力而设计。其核心定位并非替代 FatFs、LittleFS 或 ChibiOS FAT 模块等完整文件系统栈&#xff0c;而是作为上层应用…...

T/SCSIA0018-2025《四川省信息技术应用创新项目费用测算标准》标准解读

此前四川省存量信息系统信创适配改造项目长期面临费用测算无统一标准、议价争议多、成本虚高、重复计费等行业痛点&#xff0c;给项目估算、审计、结算带来诸多困扰。2025年12月29日发布的T/SCSIA0018-2025《四川省信息技术应用创新项目费用测算标准》&#xff0c;作为省内首个…...

3种方案解锁Unity游戏潜力:MelonLoader全平台模组加载器实战指南

3种方案解锁Unity游戏潜力&#xff1a;MelonLoader全平台模组加载器实战指南 【免费下载链接】MelonLoader The Worlds First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono 项目地址: https://gitcode.com/gh_mirrors/me/MelonLoader 一…...

无线通信天线与MIMO技术解析

1. 无线通信中的天线基础认知所有依赖无线通信的电子设备&#xff0c;其信号传输质量都取决于一个核心部件——天线。作为电磁波与电信号之间的转换器&#xff0c;天线性能直接决定了数据传输的稳定性和速率。在消费电子领域&#xff0c;我们最常见的天线形态主要有三种&#x…...

3步实现URL效率革命:Redirector极简方案让浏览器跳转更智能

3步实现URL效率革命&#xff1a;Redirector极简方案让浏览器跳转更智能 【免费下载链接】Redirector Browser extension (Firefox, Chrome, Opera, Edge) to redirect urls based on regex patterns, like a client side mod_rewrite. 项目地址: https://gitcode.com/gh_mirr…...