C++ asio网络编程(6)利用C11模拟伪闭包实现连接的安全回收
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、智能指针管理Session
- 二、用智能指针来实现Server的函数
- 1.start_accept()
- 1.引用计数注意点
- 2.std::bind 与异步回调函数的执行顺序分析
- 2.handle_accept
- 1.异步调用中函数执行顺序与智能指针插入顺序的问题
- 3.ClearSession
- 三、Session的uuid
- 1.Boost UUID(唯一标识符)简介与使用
- 四、Start
- shared_from_this() 使用详解
- 一、shared_from_this() 是什么?
- 二、为什么需要它?
- 三、怎么使用?
- 四、使用注意事项
- 五、使用场景:Boost.Asio 的 Session 生命周期
- 总结
- 五、读和写的回调
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
之前的异步服务器为echo模式,但其存在安全隐患,就是在极端情况下客户端关闭导致触发写和读回调函数,二者都进入错误处理逻辑,进而造成二次析构的问题。
下面我们介绍通过C11智能指针构造成一个伪闭包的状态延长session的生命周期
提示:以下是本篇文章正文内容,下面案例可供参考
一、智能指针管理Session
我们可以通过智能指针的方式管理Session类,将acceptor接收的链接保存在Session类型的智能指针里。由于智能指针会在引用计数为0时自动析构,所以为了防止其被自动回收,也方便Server管理Session
我们在Server类中添加成员变量,该变量为一个map类型,key为Session的uid,value为该Session的智能指针。
一个智能指针管理一个session
uuid是用来标识每一个session的,方便后期查找和删除这个会话
🧠 再通俗点说:
想象你是开聊天室服务器的老板,来了很多用户(Session),你得:
给每个用户一个“编号”或“身份证号” → 这就是 UUID。
把用户都存在一个表里(map)。
要踢人(断开连接)的时候,只要知道身份证号就能精准找出来删掉
class Server
{
public:Server(boost::asio::io_context& ioc, short port);void ClearSession(std::string uuid);
private:void start_accept();//监听连接void handle_accept(std::shared_ptr<Session> , const boost::system::error_code& ec);//当有连接的时候触发这个回调函数boost::asio::io_context& _ioc;//因为上下文不允许被复制 所以用引用tcp::acceptor _acceptor;std::map<std::string, std::shared_ptr<Session>>_sessions;
};
当后面在回调函数的时候,出现错误我们就将这个session从map中移除
此时管理这个session的智能指针的引用计数就会-1
不过此时不一定引用计数就会为0,说不定其他地方比如回调函数中还持有这个智能指针,因为我们在进行回调函数bind绑定的时候,通过值来传递这个智能指针,这个智能指针的引用计数也会+1
二、用智能指针来实现Server的函数
Server::Server(boost::asio::io_context& ioc, short port) :_ioc(ioc), _acceptor(ioc, tcp::endpoint(tcp::v4(), port))
{start_accept();
}void Server::start_accept()
{shared_ptr<Session>new_session=make_shared<Session>(_ioc,this);_acceptor.async_accept(new_session->Socket(),std::bind(&Server::handle_accept,this,new_session,placeholders::_1));}void Server::handle_accept(shared_ptr<Session> new_session,
const boost::system::error_code& ec)
{if (!ec)//成功{new_session->Start();_sessions.insert(make_pair(new_session->GetUuid(), new_session));}else{//delete new_session;}start_accept();//再次准备
}void Server::ClearSession(std::string uuid)
{_sessions.erase(uuid);
}
1.start_accept()
1.引用计数注意点
我们在**start_accept()**中不再用new来创建一个session,而是用一个智能指针来管理
此时重点! 我们创建了一个智能指针,此时的引用计数为1
然后我们bind中也按值传递了这个指针,此时引用计数+1
然后 start_accept() 结束 引用计数-1
然后进入 handle_accept()
2.std::bind 与异步回调函数的执行顺序分析
✅ 问题描述:
在 C++ 中,当我们使用 std::bind 将某个函数(如 B)绑定为另一个函数(如 A)的一部分时,程序的实际执行流程是怎样的?
具体来说:
如果 A 函数中使用 std::bind 绑定了 B 函数作为回调,执行流程到底是:
- 进入 A → 进入 B → 退出 B → 退出 A
- 进入 A → 退出 A → 等待某个事件 → 再执行 B → 退出 B
🧠 梳理核心概念:
这取决于 你是否立即调用了绑定后的函数对象,以及是否在 异步环境中使用它
🔍 两种情况详细分析:
🚀 情况 1:同步调用(立即执行绑定函数)
void A() {auto boundB = std::bind(B, 123);boundB(); // 立即执行
}执行流程:
进入 A↓
进入 B(因为 boundB() 被立即调用)↓
退出 B↓
退出 A
🔄 情况 2:异步绑定(比如注册回调)
void A() {socket.async_read_some(buffer, std::bind(B, placeholders::_1, placeholders::_2));
}
这里:
● std::bind(B, …) 是将 B 打包成一个回调;
● async_read_some 是注册事件,不会立刻执行;
● 所以 A 很快返回,B 要等事件触发才执行
进入 A
↓
注册回调(并不会执行 B)
↓
退出 A
↓
[某个时间点事件触发]
↓
进入 B
↓
退出 B
所以这里的 handle_read 是回调函数,它会在数据到达时异步调用,而不是在start_accept()t 中立即调用
2.handle_accept
进入 handle_accept() 如果成功就进入这个session的读写通信就行,然后将这个session插入map中
1.异步调用中函数执行顺序与智能指针插入顺序的问题
❓问题描述
在 Server::handle_accept 函数中:
if (!ec) {new_session->Start();_sessions.insert(make_pair(new_session->GetUuid(), new_session));
}
Start() 函数内部调用了 async_read_some,并使用 shared_from_this() 将当前 session 指针绑定到回调函数中。
问题在于:
● new_session->Start() 里面启动了异步通信(如 async_read_some),
● _sessions.insert(…) 是在 Start() 完成后执行的。
那么问题是:
是否必须等 Start() 里面的异步通信完成并回调走完,insert() 才会执行?
还是说,只要 Start() 同步执行完,insert() 就会马上执行?
✅答案总结
insert(…) 会在 Start() 函数同步执行完毕后立即执行,不会等待异步读写操作或其回调完成。
原因:
● async_read_some(…) 本质上只是在内部注册了一个回调函数,不阻塞当前线程,不执行回调。
● 一旦当前的 Start() 函数体执行完,就会马上回到 handle_accept 继续执行 insert(…)。
● 而回调(handle_read)只有等有客户端数据传来,触发了 IO 事件,才会异步被执行
3.ClearSession
StartAccept函数中虽然new_session是一个局部变量,但是我们通过bind操作,将new_session作为数值传递给bind函数,而bind函数返回的函数对象内部引用了该new_session所以引用计数加1,这样保证了new_session不会被释放。
在HandleAccept函数里调用session的start函数监听对端收发数据,并将session放入map中,保证session不被自动释放。
此外,需要封装一个释放函数,将session从map中移除,当其引用计数为0则自动释放
void Server::ClearSession(std::string uuid)
{_sessions.erase(uuid);
}
三、Session的uuid
1.Boost UUID(唯一标识符)简介与使用
💡 什么是 UUID?
UUID(Universally Unique Identifier)是一个标准格式的 128 位数字,它的目标是在分布式系统中生成唯一 ID,可以避免因为数据库自增或时间戳导致的冲突
格式示例:
550e8400-e29b-41d4-a716-446655440000
UUID 通常用于:
● 唯一标识某个会话(Session)
● 唯一标识某个用户、资源
● 防止 ID 冲突
● 分布式系统或网络系统中的唯一对象标识
🧰 Boost UUID 的使用
Boost 提供了 boost::uuids 命名空间中的 UUID 功能。使用非常简单,以下是步骤和示例代码:
🔌 引入头文件
#include <boost/uuid/uuid.hpp> // uuid 类型
#include <boost/uuid/uuid_generators.hpp> // 生成器
#include <boost/uuid/uuid_io.hpp> // 支持 uuid 转字符串
🛠️ 生成一个随机 UUID
boost::uuids::random_generator generator;//一个函数对象
boost::uuids::uuid id = generator();
std::string uuid_str = boost::uuids::to_string(id);std::cout << "UUID: " << uuid_str << std::endl;
✅ random_generator() 使用系统随机数生成 UUID,符合 UUID v4(随机生成版本)
✅ 常见用法:类中作为 Session 唯一标识符
class Session {
public:Session() {boost::uuids::uuid uid = boost::uuids::random_generator()();_uuid = boost::uuids::to_string(uid);}std::string GetUuid() const { return _uuid; }private:std::string _uuid;
};
⚠️ 注意事项
● uuid 类型本身不是字符串,它是一个 16 字节数组。需要用 boost::uuids::to_string() 转成字符串。
● 生成器对象可以复用,但你也可以每次临时构造
📝 小结
● Boost.UUID 是生成唯一 ID 的利器,适合在网络通信、分布式系统、资源标识中使用。
● 在你当前写的 Session 类中用它生成 UUID,再放入 map<string, shared_ptr> 管理,非常合适。
● 常用接口是 random_generator() + to_string()
四、Start
我们进入Start函数中,我们用准备bind读函数
void Session::Start()
{memset(_data, 0, sizeof(_data));_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this, placeholders::_1, placeholders::_2,shared_from_this()));}
我们知道我们要传入智能指针来管理
这里我们用shared_from_this()
因为这是这个Session本身的智能指针,就是在前面创造出来的,这里相当于自己的副本,这样会使得引用计数同步,就不会导致前面的已经析构了,但这里还在
shared_from_this() 使用详解
一、shared_from_this() 是什么?
shared_from_this() 是 std::enable_shared_from_this 提供的成员函数,用于在类的成员函数中获取当前对象的 shared_ptr 智能指针副本。
它的作用是:
✅ 在类对象已经被 shared_ptr 管理时,从内部安全地获取它自己的智能指针副本
二、为什么需要它?
如果你在类成员函数中通过 this 传递当前对象的裸指针给外部(如异步回调),可能在异步调用发生前对象就已被销毁,导致程序崩溃(悬空指针)
boost::asio::async_read(_socket, buffer,std::bind(&Session::handle_read, this, ...)); // ⚠️ 非安全
使用 shared_from_this() 可以延长对象生命周期,保证在异步回调中对象仍然有效
三、怎么使用?
1.继承 std::enable_shared_from_this
class Session : public std::enable_shared_from_this<Session>
{...
};
2.在类成员函数中使用 shared_from_this()
void Session::Start() {auto self = shared_from_this();boost::asio::async_read(_socket, buffer,std::bind(&Session::handle_read, self, ...)); // ✅ 绑定智能指针,防止提前析构
}
四、使用注意事项
五、使用场景:Boost.Asio 的 Session 生命周期
当前 Boost.Asio 的服务端代码中,Session 表示一个客户端连接,异步读取时这样使用:
_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this, ..., shared_from_this()));
这里的 shared_from_this() 是为了把当前对象打包成 shared_ptr,传递给回调,确保异步过程中不会被提前销毁
总结
● shared_from_this() 适合需要延长对象生命周期的场景,尤其是异步/回调中。
● 使用前务必确保对象由 shared_ptr 创建。
● 适用于资源敏感类、异步类、会话类等典型需求
五、读和写的回调
在读和写的回调中我们分别传入管理这个session的智能指针就行,然后如果出错,就从map中移除就行,后续bind结束后就会逐渐的使得引用计数-1 当为0的时候就自动析了
//读的回调函数
void Session::handle_read(const boost::system::error_code& ec, size_t bytes_transferred, shared_ptr<Session>_self_shared)
{if (ec)//0正确 1错误{cout << "read error" << endl;//delete this;_server->ClearSession(_uuid);}else{cout << "server receivr data is "<<_data << endl;//将收到的数据发送回去boost::asio::async_write(_socket, boost::asio::buffer(_data, bytes_transferred),std::bind(&Session::handle_write,this, placeholders::_1, placeholders::_2, _self_shared));}
}//写的回调函数
void Session::handle_write(const boost::system::error_code& ec, size_t
bytes_transferred,shared_ptr<Session>_self_shared)
{ if (ec)//0正确 1错误{cout << "write error" << endl;_server->ClearSession(_uuid);}else{//发完了 就清除掉原先的memset(_data, 0, sizeof(_data));//继续读_socket.async_read_some(boost::asio::buffer(_data, bytes_transferred),std::bind(&Session::handle_read, this, placeholders::_1, placeholders::_2, _self_shared));}
}
总结
我们通过C11的bind和智能指针实现了类似于go,js等语言的闭包功能,保证在回调函数触发之前Session都是存活的
相关文章:
C++ asio网络编程(6)利用C11模拟伪闭包实现连接的安全回收
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、智能指针管理Session二、用智能指针来实现Server的函数1.start_accept()1.引用计数注意点2.std::bind 与异步回调函数的执行顺序分析 2.handle_accept1.异步…...
【视频】解决FFmpeg将RTSP转RTMP流时,出现的卡死、出错等问题
1、简述 如果不修改图像内容,可以使用FFmpeg命令来将RTSP转RTMP流。 SRS视频服务器就是这么干的,它没有使用FFmpeg接口,而是直接使用FFmpeg命令来转流。 但是在使用中,约到了一些问题,比如转流时卡死、转流出错等等,下面描述怎么解决这些问题 2、出错重启 在shell脚本…...
飞牛NAS本地部署开源TTS文本转语音工具EasyVoice与远程使用流程
文章目录 前言1. 环境准备2. Docker部署与运行3. 简单使用测试4. 安装内网穿透4.1 开启ssh连接安装cpolar4.2 创建公网地址 5. 配置固定公网地址总结 前言 本文主要介绍如何在fnOS飞牛云NAS使用Docker本地部署一款非常好用的开源TTS文本转语音工具EasyVoice,并结合…...
STC51系列单片机引脚分类与功能速查表(以STC89C52为例)
1. 基本I/O端口 端口引脚范围类型主要功能特殊说明P0P0.0~P0.7开漏双向I/O1. 通用I/O(需外接上拉电阻) 2. 数据总线(D0-D7) 3. 低8位地址总线(A0-A…...
recvfrom和sendto函数中地址参数的作用
在 UDP 通信中,recvfrom 和 sendto 函数中的地址参数起着至关重要的作用。 以下是对这两个函数中地址参数的作用、所属方以及缺失地址时的后果的详细解释。 recvfrom 函数 int recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_add…...
运维职业发展思维导图
主要内容如下: 一、 初级入行阶段 这是职业生涯的起点,主要涉及基础技能的学习和实践。 Linux初学: 重点是学习Linux系统的基础命令和操作。IDC机房运维: 负责数据中心机房内设备的管理和日常维护工作。Helpdesk桌面运维: 提供桌面技术支持,帮助用户解决遇到的计算机软硬…...
【数据处理】Python对CMIP6数据进行插值——详细解析实现(附源码)
目录 Python对CMIP6数据进行插值一、引言代码概览思维导图 二、数据预处理三、数据区域裁剪四、插值(一) 垂直插值(二) 水平插值 五、保存插值好的文件六、文件合并与气候态计算七、代码优化技巧八、多线程处理九、全部代码 Pytho…...
worldquant rank函数
https://support.worldquantbrain.com/hc/en-us/community/posts/13869304934935-%E6%80%8E%E6%A0%B7%E7%90%86%E8%A7%A3rank%E5%87%BD%E6%95%B0 链接。进的话可以填我的邀请码JS34795我可以带你 现在学习rank函数 我们所说的做多和做空 首先,当我们讨论Long和S…...
工业4.0神经嫁接术:ethernet ip转profinet协议通信步骤图解
在现代工业自动化领域,不同品牌的设备和协议之间的兼容性问题一直是个挑战。我们的包装线项目就遇到了这样的难题:需要将Rockwell Allen-Bradley的EtherNet/IP伺服系统与西门子PLC的PROFINET主站进行无缝对接。为了解决这一问题,我们采用了et…...
数据库——数据操作语言DML
(2)数据操作语言DML 简称DML——Data Manipulation Language用来对数据库中表的记录进行更新关键字:insert,delete,update A、 插入表记录 向表中插入数据 格式:insert into 表名(字段1,字段2,字段3……) values(值1,值2,值3);…...
文件防泄密的措施有哪些?
文件防泄密措施需要从技术、管理和物理三个层面综合施策,以下为常见措施分类整理: 一、技术防护措施 华途加密技术 文件加密:使用AES、RSA等算法对敏感文件加密。 传输加密:通过SSL/TLS、VPN保障传输安全,禁止明文传…...
C++ Mac 打包运行方案(cmake)
文章目录 背景动态库梳理打包方案静态库处理动态库处理(PCL库)编译链接动态库后处理逻辑 批量信任 背景 使用C编写的一个小项目,需要打包成mac下的可执行文件(免安装版本),方便分发给其他mac执行,需要把项目的动态库都…...
数学复习笔记 10
前言 我觉得数学的高分乃至满分属于那些,聪明,坚韧,勇敢,细致的人。我非常惭愧自己不是这样的人,我在生活中发现了这样的同学,和他们交流的时候我常常感到汗流浃背,因为他们非常扎实的基础知识…...
Oracle-相关笔记
Oracle Database Online Documentation 11g 连接 WinR sqlplus username/passwordhostname:port/service_namesqlplus user02/123456192.xxx:1521/orclsqlplus / as sysdba #SQL*Plus 終端编码使用UTF-8 chcp 65001#打开SQL*Plus程序 sqlplus /nolog#使用dba角色登录(用 1.…...
mac安装cast
背景 pycharm本地运行脚本时提示cast没有安装 问题原因 脚本尝试调用cast命令(以太坊开发工具foundry中的子命令),但您的系统未安装该工具。 从日志可见,错误发生在通过sysutil.py执行shell命令时。 解决方案 方法1…...
CodeEdit:macOS上一款可以让Xcode退休的IDE
CodeEdit 是一款轻量级、原生构建的代码编辑器,完全免费且开源。它使用纯 swift 实现,而且专为 macOS 设计,旨在为开发者提供更高效、更可靠的编程环境,同时释放 Mac 的全部潜力。 Stars 数21,719Forks 数1,081 主要特点 macOS 原…...
opencv4.11编译Debug提示缺少python312_d.lib或python3*_d.lib的解决办法
前言 当我们编译OpenCV 4.11的时候可能会遇到提示缺少库文件,这个时候我们可以下载Python源码编译这个lib。 也可以下载我上传的版本(python312_d.lib),但是如果是其他版本需要自己编译。编译步骤如下,大概几分钟搞定…...
html的鼠标点击事件有哪些写法
在HTML中,鼠标点击事件的实现方式多样,以下从基础语法到现代实践为您详细梳理: 一、基础写法:直接内联事件属性 在HTML标签内通过on前缀事件属性绑定处理函数,适合简单交互场景: <!-- 单击事件 -->…...
深度解析物理机服务器故障修复时间:影响因素与优化策略
一、物理机故障修复的核心影响因素 物理机作为企业 IT 基础设施的核心载体,其故障修复效率直接关系到业务连续性。故障修复时间(MTTR)受多重因素交叉影响: 1. 故障类型的复杂性 硬件级故障: 简单故障:内存…...
蓝桥杯 2024 C++国 B最小字符串
P10910 [蓝桥杯 2024 国 B] 最小字符串 题目描述 给定一个长度为 N N N 且只包含小写字母的字符串 S S S,和 M M M 个小写字母 c 1 , c 2 , ⋯ , c M c_1, c_2, \cdots, c_M c1,c2,⋯,cM。现在你要把 M M M 个小写字母全部插入到字符串 S S S 中&…...
解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs-docker MCP解析
解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs-docker MCP解析 这里面有很重要的原因其中一个很其中一个原因是因为如果你使用docker的方式,你可以在虚拟环境下就类似于这个沙箱的这个机制可以进行隔离。这对于安全,…...
访问 Docker 官方镜像源(包括代理)全部被“重置连接”或超时
华为云轻量应用服务器(Ubuntu 系统) 遇到的问题是: 🔒 访问 Docker 官方镜像源(包括代理)全部被“重置连接”或超时了,说明你这台服务器的出境网络对这些国外域名限制很严格,常见于华…...
前馈神经网络回归(ANN Regression)从原理到实战
前馈神经网络回归(ANN Regression)从原理到实战 一、回归问题与前馈神经网络的适配性分析 在机器学习领域,回归任务旨在建立输入特征与连续型输出变量之间的映射关系。前馈神经网络(Feedforward Neural Network)作为最基础的神经网络架构&a…...
RNN/LSTM原理与 PyTorch 时间序列预测实战
🕰️ RNN / LSTM 原理与 PyTorch 时间序列预测实战 在处理时间序列数据、语音信号、文本序列等连续性强的问题时,循环神经网络(RNN)及其改进版本 LSTM(长短期记忆网络)是最常见也最有效的模型之一。本文将深入讲解 RNN 和 LSTM 的核心原理,并通过 PyTorch 实现一个时间…...
Docker容器镜像与容器常用操作指南
一、镜像基础操作 搜索镜像 docker search <镜像名>在Docker Hub中查找公开镜像,例如: docker search nginx拉取镜像 docker pull <镜像名>:<标签>从仓库拉取镜像到本地,标签默认为latest: docker pull nginx:a…...
1:OpenCV—图像基础
OpenCV教程 头文件 您只需要在程序中包含 opencv2/opencv.hpp 头文件。该头文件将包含应用程序的所有其他必需头文件。因此,您不再需要费心考虑程序应包含哪些头文件。 例如 - #include <opencv2/opencv.hpp>命名空间 所有 OpenCV 类和函数都在 cv 命名空…...
测试--BUG(软件测试⽣命周期 bug的⽣命周期 与开发产⽣争执怎么办)
1. 软件测试的⽣命周期 软件测试贯穿于软件的整个⽣命周期,针对这句话我们⼀起来看⼀下软件测试是如何贯穿软件的整个⽣命周期。 软件测试的⽣命周期是指测试流程,这个流程是按照⼀定顺序执⾏的⼀系列特定的步骤,去保证产品质量符合需求。在软…...
基于大模型预测围术期麻醉苏醒时间的技术方案
目录 一、数据收集与处理(一)数据来源(二)数据预处理二、大模型构建与训练(一)模型选择(二)模型训练三、围术期麻醉苏醒时间预测(一)术前预测(二)术中动态预测四、并发症风险预测(一)风险因素分析(二)风险预测模型五、基于预测制定手术方案(一)个性化手术规划…...
QT6 源(101)阅读与注释 QPlainTextEdit,其继承于QAbstractScrollArea,属性学习与测试
(1) (2) (3)属性学习与测试 : (4) (5) 谢谢...
电池组PACK自动化生产线:多领域电池生产的“智能引擎”
在电池产业蓬勃发展的当下,电池组PACK自动化生产线凭借其高效、精准、智能的优势,成为众多电池生产领域的核心装备。它广泛适用于数码电池、工具电池、储能电池、电动车电池以及动力电池的生产,有力推动了相关产业的升级与发展。 数码电池领…...
生成式AI在编程中的应用场景:从代码生成到安全检测
引言 生成式AI正在深刻改变软件开发的方式,从代码编写到测试、文档和维护,AI技术正在为每个环节带来革命性的变革。本文将深入探讨生成式AI在编程中的主要应用场景,分析其优势与局限性,并展望未来发展趋势。 主要应用场景 1. 代…...
安全牛报告解读《低空经济发展白皮书(3.0)安全体系》
一、概述 《低空经济发展白皮书(3.0)安全体系》由粤港澳大湾区数字经济研究院(IDEA研究院)发布,旨在构建低空经济安全发展的系统性框架,解决规模化低空飞行中的安全挑战。核心目标是明确安全体系需覆盖的飞…...
“2W2H”分析方法
“2W2H”是一种常用的分析方法,它通过回答**What(是什么)、Why(为什么)、How(怎么做)、How much(多少)**这四个问题来全面了解和分析一个事物或问题。这种方法可以帮助你…...
【数据挖掘笔记】兴趣度度量Interest of an association rule
在数据挖掘中,关联规则挖掘是一个重要的任务。兴趣度度量是评估关联规则的重要指标,以下是三个常用的兴趣度度量:支持度、置信度和提升度。 支持度(Support) 计算方法 支持度表示包含项集的事务占总事务的比例&…...
ArcGIS Pro调用多期历史影像
一、访问World Imagery Wayback,基本在我国范围 如下图: 二、 放大到您感兴趣的区域 三、 查看影像版本信息 点击第二步的按钮后,便可跳转至World Imagery (Wayback 2025-04-24)的相关信息。 四 、点击上图影像版本信息,页面跳转…...
Web3.0:互联网的去中心化未来
随着互联网技术的不断发展,我们正站在一个新时代的门槛上——Web3.0时代。Web3.0不仅仅是一个技术升级,它更是一种全新的互联网理念,旨在通过去中心化技术重塑网络世界。本文将深入探讨Web3.0的核心概念、技术基础、应用场景以及它对未来的深…...
java17
1.常见API之BigDecimal 底层存储方式: 2.如何分辨过时代码: 有横线的代码表示该代码已过时 3.正则表达式之字符串匹配 注意:如果X不是单一字符,需要加[]中括号 注意:1.想要表达正则表达式里面的.需要\\. 2.想要表…...
游戏引擎学习第283天:“让‘Standing-on’成为一个更严谨的概念
如果同时使用多个OpenGL上下文,并且它们都有工作负载,GPU或GPU驱动程序如何决定调度这些工作?我注意到Windows似乎优先处理活动窗口的OpenGL上下文(即活动窗口表现更好),挺有意思的…… 当多个OpenGL上下文…...
小白上手RPM包制作
目录 rpm常用命令 安装环境-Ruby 安装环境-fpm 关于服务器 打包-打包二进制工程 .fpm配置文件 打包-打没有文件的包 RPM 包微调 命令行参数 fpm --help RPM 签名 打包-制作NGINX的RPM包 关于rpmbuild 简单使用 打包之前的准备工作 rpmbuild 打包 - sniproxy …...
电商热销榜的5种实现方案
文章目录 1. MySQL 聚合查询:传统统计法2. Redis Sorted Set:内存排行榜3. Elasticsearch 实时聚合:搜索专家4. 缓存异步更新:榜单的幕后推手5. 大数据离线批处理:夜间魔法师 博主介绍:全网粉丝10w、CSDN合…...
车载诊断进阶篇 --- 车载诊断概念
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...
AD 多层线路及装配图PDF的输出
装配图的输出: 1.点开‘智能PDF’ 2. 设置显示顶层: 设置显示底层: 多层线路的输出 同样使用‘智能PDF’...
FramePack - 开源 AI 视频生成工具
🎬 项目简介 由开发者 lllyasviel 创建的一个轻量级动画帧处理工具库,专门用于游戏开发、动画制作和视频处理中的帧序列打包与管理。该项目采用高效的算法实现,能够显著提升动画资源的处理效率。 此 AI 视频生成项目,旨在通过低显…...
“this”这个关键字
一、什么是“this”? 简单来说,“this”是每个非静态成员函数隐含的指针,它指向调用该成员函数的那个对象本身。 换句话说,当你调用对象的方法时,编译器会自动传入一个指针,指向你调用的“那个对象”&…...
问题处理——在ROS2(humble)+Gazebo+rqt下,无法显示仿真无人机的相机图像
文章目录 前言一、问题展示二、解决方法:1.下载对应版本的PX42.下载对应版本的Gazebo3.启动 总结 前言 在ROS2的环境下,进行无人机仿真的过程中,有时需要调取无人机的相机图像信息,但是使用rqt,却发现相机图像无法显示…...
广度和深度优先搜索(BFS和DFS)
1. 广度和深度优先搜索(BFS和DFS) 1.1. Python实现BFS和DFS from collections import dequeclass Graph:"""无向图类,支持添加边,并实现了 BFS(广度优先搜索)和 DFS(深度优先搜…...
React和Vue在前端开发中, 通常选择哪一个
React和Vue的选择需结合具体需求: 选React的场景 大型企业级应用,需处理复杂状态(如电商、社交平台)团队熟悉JavaScript,已有React技术栈积累需要高度灵活的架构(React仅专注视图层,可自由搭配…...
Vue3学习(组合式API——reactive()和ref()函数详解)
目录 一、reactive()函数。 (1)介绍与使用。 (2)简单案例演示。 二、ref()函数。 (1)介绍与使用。 (2)简单案例演示。 <1>ref()函数获取响应式对象的本质与底层。 <2>基…...
数据结构 -- 树形查找(一)二叉排序树
二叉排序树 二叉排序树的定义 二叉排序树,又称二叉查找树 一棵二叉树或者是空二叉树,或者是具有以下性质的二叉树: 左子树上所有结点的关键字均小于根结点的关键字 右子树上所有结点的关键字均大于根结点的关键字 左子树和右子树又各是…...
【实战教程】从零实现DeepSeek AI多专家协作系统 - Spring Boot+React打造AI专家团队协作平台
🚀 本项目是DeepSeek大模型应用系列的V3版本,基于V1和V2版本的功能进行全面升级,引入了多智能体协作机制! 系列教程推荐阅读顺序: 【V1版本】零基础搭建DeepSeek大模型聊天系统 - Spring BootReact完整开发指南【V2版本…...