netty-socketio + springboot 消息推送服务
netty-socketio + springboot 消息推送服务
- 后端
- 1. 目录结构:
- 代码
- pom文件:
- application.yml:
- SocketIOConfig:
- PushMessage:
- ISocketIOService
- SocketIOServiceImpl:
- pushMessageController:
- 启动类:MessagePushDemo:
- 前端
- 安装客户端
- client.js
- 参考文档:
-
背景:后端业务代码中调用这个消息推送服务,主动推送消息给客户端。前端(客户端)连接 消息推送服务,并可以实时的收到服务器发来的消息。
-
注意点:客户端与服务器(netty-socketio)版本不兼容会导致:客户端链接服务端成功,但是收不到服务端发来的消息。官方推荐的版本匹配。
-
文章参考文档放在最后
后端
1. 目录结构:
代码
pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>messagePushDemo</artifactId><version>1.0-SNAPSHOT</version><properties>
<!-- <maven.compiler.source>11</maven.compiler.source>-->
<!-- <maven.compiler.target>11</maven.compiler.target>--><swagger.core.version>1.6.2</swagger.core.version><java.version>1.8</java.version></properties>
<!-- <packaging>jar</packaging>--><!-- <name>messagePushDemo</name>-->
<!-- <url>http://maven.apache.org</url>--><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.0.0.RELEASE</version></parent><dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.13.0</version></dependency><!-- Swagger 依赖配置 --><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>${swagger.core.version}</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>${swagger.core.version}</version></dependency><!-- Spring MVC依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springBoot的Test依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.49.Final</version></dependency><dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>1.7.19</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.73</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version></plugin></plugins></build></project>
application.yml:
# Tomcat
server:port: 8080socketio:# host在本地测试可以设置为localhost或者本机IPhost: localhostport: 9099# 在Linux服务器跑可换成服务器外网IPpublic:host: localhostallowCustomRequests: true# socket连接数大小(如只监听一个端口boss线程组为1即可)bossCount: 1# 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器maxFramePayloadLength: 1048576# 设置http交互最大内容长度maxHttpContentLength: 1048576# Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔pingInterval: 25000# Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件pingTimeout: 6000000# 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间upgradeTimeout: 1000000workCount: 100
SocketIOConfig:
import com.corundumstudio.socketio.SocketConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.corundumstudio.socketio.SocketIOServer;@Configuration
public class SocketIOConfig {@Value("${socketio.host}")private String host;@Value("${socketio.port}")private Integer port;@Value("${socketio.bossCount}")private int bossCount;@Value("${socketio.workCount}")private int workCount;@Value("${socketio.allowCustomRequests}")private boolean allowCustomRequests;@Value("${socketio.upgradeTimeout}")private int upgradeTimeout;@Value("${socketio.pingTimeout}")private int pingTimeout;@Value("${socketio.pingInterval}")private int pingInterval;/*** 以下配置在上面的application.properties中已经注明* @return*/@Beanpublic SocketIOServer socketIOServer() {SocketConfig socketConfig = new SocketConfig();socketConfig.setTcpNoDelay(true);socketConfig.setSoLinger(0);com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();config.setSocketConfig(socketConfig);config.setHostname(host);config.setPort(port);config.setBossThreads(bossCount);config.setWorkerThreads(workCount);config.setAllowCustomRequests(allowCustomRequests);config.setUpgradeTimeout(upgradeTimeout);config.setPingTimeout(pingTimeout);config.setPingInterval(pingInterval);return new SocketIOServer(config);}
}
PushMessage:
package org.example.msg;import io.swagger.annotations.ApiModelProperty;
public class PushMessage {@ApiModelProperty(value = "登录用户编号/唯一标识")private String clientId;@ApiModelProperty(value = "推送事件")private String event;@ApiModelProperty(value = "推送内容")private String content;public PushMessage() {}public PushMessage(String clientId, String event, String content) {this.clientId = clientId;this.event = event;this.content = content;}private PushMessage(Builder builder) {setClientId(builder.clientId);setEvent(builder.event);setContent(builder.content);}public static Builder newBuilder() {return new Builder();}public String getClientId() {return clientId;}public void setClientId(String clientId) {this.clientId = clientId;}public String getEvent() {return event;}public void setEvent(String event) {this.event = event;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public static final class Builder {private String clientId;private String event;private String content;private Builder() {}public Builder clientId(String val) {clientId = val;return this;}public Builder event(String val) {event = val;return this;}public Builder content(String val) {content = val;return this;}public PushMessage build() {return new PushMessage(this);}}
}
ISocketIOService
package org.example.service;import org.example.msg.PushMessage;public interface ISocketIOService {/*** 推送的事件*/String PUSH_EVENT = "push_event";/*** 聊天的事件*/String IM_EVENT = "im_event";/*** 登录的事件*/String LOGIN_EVENT = "login_event";/*** 启动服务*/void start() throws Exception;/*** 停止服务*/void stop();/*** 推送信息*/void pushMessageToUser(PushMessage pushMessage);
}
SocketIOServiceImpl:
package org.example.service.impl;import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.lang3.StringUtils;
import org.example.msg.PushMessage;
import org.example.service.ISocketIOService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;import static org.example.service.ISocketIOService.IM_EVENT;
import static org.example.service.ISocketIOService.PUSH_EVENT;@Service(value = "socketIOService")
public class SocketIOServiceImpl implements ISocketIOService {private Logger logger = LoggerFactory.getLogger(SocketIOServiceImpl.class);/*** 用来存已连接的客户端*/private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();@Autowiredprivate SocketIOServer server;/*** Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动* @throws Exception*/@PostConstructprivate void autoStartup() throws Exception {start();}/*** Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题* @throws Exception*/@PreDestroyprivate void autoStop() throws Exception {stop();}@Overridepublic void start() {// 监听客户端连接server.addConnectListener(client -> {String clientId = getParamsByClient(client);if (clientId != null) {if (clientMap.isEmpty()) {clientMap.put(clientId, client);logger.info("clientId: {} connected...", clientId);}else {if (clientMap.containsKey(clientId)) {SocketIOClient preClient = clientMap.get(clientId);preClient.disconnect();logger.info("旧链接已断开");}clientMap.put(clientId, client);logger.info("clientId: {} connected...", clientId);}}});// 监听客户端断开连接server.addDisconnectListener(client -> {String clientId = getParamsByClient(client);if (clientId != null) {clientMap.remove(clientId);client.disconnect();logger.info("clientId: {} disconnected...", clientId);}});// 处理自定义的事件,与连接监听类似server.addEventListener(PUSH_EVENT, PushMessage.class, (client, data, ackSender) -> {logger.info("eventListener data: {}", data);});server.addEventListener(IM_EVENT, PushMessage.class, (client, data, ackSender) -> {logger.info("eventListener data: {}", data);});server.start();}@Overridepublic void stop() {if (server != null) {server.stop();server = null;logger.info("server stop!");}}@Overridepublic void pushMessageToUser(PushMessage pushMessage) {String clientIds = pushMessage.getClientId();if (StringUtils.isNotBlank(clientIds)) {for (String clientId : clientIds.split(",")) {SocketIOClient client = clientMap.get(clientId);if (client != null) {client.sendEvent(pushMessage.getEvent(), pushMessage.getContent());logger.info("push message: {}, toClientId: {}", pushMessage.getContent(), clientId);}else {logger.info("当前客户端无连接");}}}}/*** 此方法为获取client连接中的参数,可根据需求更改* @param client* @return*/private String getParamsByClient(SocketIOClient client) {// 从请求的连接中拿出参数(这里的clientId必须是唯一标识)return client.getHandshakeData().getSingleUrlParam("clientId");}
}
pushMessageController:
package org.example.controller;import org.example.msg.PushMessage;
import org.example.service.ISocketIOService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class pushMessageController {@Autowiredprivate ISocketIOService socketIOService;@GetMapping("/im/push")@ResponseBodypublic String pushMessage(@RequestParam String clientId,@RequestParam String content){if (clientId == null || clientId.isEmpty()){return "参数为空错误";}PushMessage pushMessage = new PushMessage(clientId, ISocketIOService.IM_EVENT, content);socketIOService.pushMessageToUser(pushMessage);return "success";}}
启动类:MessagePushDemo:
package org.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Hello world!**/
@SpringBootApplication
public class MessagePushDemo
{public static void main( String[] args ){SpringApplication.run(MessagePushDemo.class, args);
// System.out.println( "Hello World!" );}
}
前端
安装客户端
npm install socket.io-client@2
我安装的2开头的版本,注意和服务器的版本兼容
client.js
const io = require('socket.io-client');// 配置连接选项
const options = {// 开启重连机制reconnection: true, // 最大重连次数reconnectionAttempts: Infinity, // 重连间隔时间,初始为 1000 毫秒reconnectionDelay: 1000, // 重连间隔时间上限,最大为 5000 毫秒reconnectionDelayMax: 5000, // 连接超时时间,设置为 10000 毫秒timeout: 10000
};// 使用配置选项连接到服务器
const socket = io('http://localhost:9099?clientId=122', options);// 监听连接成功事件
socket.on('connect', () => {console.log('连接成功');
});// 监听事件
socket.on('im_event', (msg) => {console.log('事件内容:', msg);
});// 监听连接错误事件
//socket.on('connect_error', (error) => {
// console.error('连接错误:', error);
//});// 监听断开连接事件
socket.on('disconnect', () => {console.log('连接已断开');
});
参考文档:
socket.io官方文档
代码原博主文章
相关文章:
netty-socketio + springboot 消息推送服务
netty-socketio springboot 消息推送服务 后端1. 目录结构:代码pom文件:application.yml:SocketIOConfig:PushMessage:ISocketIOServiceSocketIOServiceImpl:pushMessageController:启动类&…...
基于 JavaWeb 的 SSM 在线视频教育系统设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
同时打开多个Microchip MPLAB X IDE
0.引用 Microchip 32位MCU CAN驱动图文教程-附源码 - 哔哩哔哩 https://bbs.21ic.com/icview-3391426-1-1.html https://bbs.21ic.com/icview-3393632-1-1.html 1.前言 工作中接触到使用Microchip 的 MPLAB X IDE 开发工具,使用的MCU是Microchip SAMD21J18A MCU…...
dify 500错误
问题 升级到1.2.0 后所有页面接口均报错500, 环境: docker 本地部署 version:1.2.0 解决办法 1.首先关闭服务 docker compose down2.找到docker-compose.yaml里的plugin_daemon,参照下面修改参数 plugin_daemon:environment:PLUGIN_MAX_EXECUTION…...
WPF设计标准学习记录26
画刷名称功能说明SolidColorBrush使用单一的连续颜色填充区域LinearGradientBrush使用线性渐变绘制区域。RadialGradientBrush使用径向渐变绘制区域。 焦点定义渐变的开始,而圆定义渐变的终点。ImageBrush使用图像绘制区域。VisualBrush使用一个视图绘制区域。BitmapCacheBrus…...
cin,cin.get(),getchar(),getline(),cin.get line()异同点
文章目录 1.cin2.cin.get()3.getchar()4.cin.getline()5.getline() 1.cin (1)cin>>等价于cin.operator>>(),即调用成员函数operator>>()进行读取数据。 (2)当cin>>从缓冲区中读取数据时&…...
7# 5多线-7 不会停
7# 5多线-7 不会停 分析,明显线接错了,打自动时也能手动启停,打手动无法启停,这时远程只能启ka3,无法启ka4。排查手自转换2上没接线,接到8上了(13和12接错了,也就是sac的5和6接错了)…...
基于混合编码器和边缘引导的拉普拉斯金字塔网络用于遥感变化检测
Laplacian Pyramid Network With HybridEncoder and Edge Guidance for RemoteSensing Change Detection 0、摘要 遥感变化检测(CD)是观测和分析动态土地覆盖变化的一项关键任务。许多基于深度学习的CD方法表现出强大的性能,但它们的有效性…...
机器学习 从入门到精通 day_04
1. 决策树-分类 1.1 概念 1. 决策节点 通过条件判断而进行分支选择的节点。如:将某个样本中的属性值(特征值)与决策节点上的值进行比较,从而判断它的流向。 2. 叶子节点 没有子节点的节点,表示最终的决策结果。 3. 决策树的…...
CLAHE算法介绍
限制对比度自适应直方图增强 CLAHE 算法介绍 1. CLAHE算法框图2.直方图clip及重分配2.1 opencv自带2.2 scikit-image2.3 结果对比2.4 clip limit的性质3.插值参考文献上图来自 K. Zuiderveld: Contrast Limited Adaptive Histogram Equalization。 图中可以看到各种直方图均衡的…...
高并发的业务场景下,如何防止数据库事务死锁
一、 一致的锁定顺序 定义: 死锁的常见原因之一是不同的事务以不同的顺序获取锁。当多个事务获取了不同资源的锁,并且这些资源之间发生了互相依赖,就会形成死锁。 解决方法: 确保所有的事务在获取多个锁时,按照相同的顺序请求锁。例如,如果事务A需要锁定表A和表B,事务…...
使用Python从零实现一个端到端多模态 Transformer大模型
嘿,各位!今天咱们要来一场超级酷炫的多模态 Transformer 冒险之旅!想象一下,让一个模型既能看懂图片,又能理解文字,然后还能生成有趣的回答。听起来是不是很像超级英雄的超能力?别急,…...
elestio memos SSRF漏洞复现(CVE-2025-22952)(附脚本)
免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 前言…...
倚光科技:以创新之光,雕琢全球领先光学设计公司
在光学技术飞速发展的当下,每一次突破都可能为众多领域带来变革性的影响。而倚光(深圳)科技有限公司,作为光学设计公司的一颗璀璨之星,正以其卓越的创新能力和深厚的技术底蕴,引领着光学设计行业的发展潮流…...
Linux安装Elasticsearch详细教程
准备工作 下载地址:Download Elasticsearch | Elastic 下载时需要注意es与jdk版本对应关系 ES 7.x 及之前版本,选择 Java 8 ES 8.x 及之后版本,选择 Java 17 或者 Java 18,建议 Java 17,因为对应版本的 Logstash 不支持 Java 1…...
C++字符串操作详解
引言 字符串处理是编程中最常见的任务之一,而在C中,我们有多种处理字符串的方式。本文将详细介绍C中的字符串操作,包括C风格字符串和C的string类。无论你是C新手还是想巩固基础的老手,这篇文章都能帮你梳理字符串处理的关键知识点…...
PromptPro|提示词生成和管理专家
大家好,我是吾鳴。 今天吾鳴给大家分享一个实用的提示词管理网站,它的名称叫做产品化管理提示词,英文名叫做PromptPro,是一个可以帮你管理你的大模型提示词的网站,同时你也可以告诉它你的需求,让它帮你生成…...
计算机视觉图像特征提取入门:Harris角点与SIFT算法
计算机视觉图像特征提取入门:Harris角点与SIFT算法 一、前言二、Harris 角点检测算法2.1 Harris 角点的定义与直观理解2.1.1 角点的概念2.1.2 Harris 角点的判定依据 2.2 Harris 角点检测的实现步骤2.2.1 计算图像的梯度2.2.2 构建结构张量矩阵2.2.3 …...
swift菜鸟教程1-5(语法,变量,类型,常量,字面量)
一个朴实无华的目录 今日学习内容:1.基本语法引入空格规范输入输出 2.变量声明变量变量输出加反斜杠括号 \\( ) 3.可选(Optionals)类型可选类型强制解析可选绑定 4.常量常量声明常量命名 5.字面量整数 and 浮点数 实例字符串 实例 今日学习内容: 1.基本…...
02142数据结构导论
初学者,怎样理解这道题,怎样大白话分析 答案解析 00、概念 29、 28、 27、 26、 25、 24、 23、 22、有5个元素,其入栈次序为:A、B、C、D、E,写出以元素C、D最先出栈(即C第一个且D第二个出栈)的各种可能的出栈次序。 (来…...
如何在AMD MI300X 服务器上部署 DeepSeek R1模型?
DeepSeek-R1凭借其深度推理能力备受关注,在语言模型性能基准测试中可与顶级闭源模型匹敌。 AMD Instinct MI300X GPU可在单节点上高效运行新发布的DeepSeek-R1和V3模型。 用户通过SGLang优化,将MI300X的性能提升至初始版本的4倍,且更多优化将…...
【Django】教程-15-注册页面
【Django】教程-1-安装创建项目目录结构介绍 【Django】教程-2-前端-目录结构介绍 【Django】教程-3-数据库相关介绍 【Django】教程-4-一个增删改查的Demo 【Django】教程-5-ModelForm增删改查规则校验【正则钩子函数】 【Django】教程-6-搜索框-条件查询前后端 【Django】教程…...
OpenAI即将上线新一代重磅选手——GPT-4.1
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
参照Spring Boot后端框架实现序列化工具类
本文参照Jackson实现序列化工具类,旨在于简化开发 JacksonUtil.class public class JacksonUtil {private JacksonUtil() {}/*** 单例*/private final static ObjectMapper OBJECT_MAPPER;static {OBJECT_MAPPER new ObjectMapper();}private static ObjectMappe…...
C_内存 内存地址概念
1. 计算机内存的基本概念 计算机的内存(RAM,随机存取存储器)是用来存储程序运行时的数据和指令的地方。内存被划分为许多小单元,每个单元有一个唯一的地址,这些地址从0开始编号。 内存单元:每个内存单元通…...
Rust重定义数据库内核:从内存安全到性能革命的破界之路
Rust语言正在颠覆传统数据库开发范式,其独特的所有权系统与零成本抽象能力,为攻克C/C时代遗留的内存泄漏、并发缺陷等顽疾提供全新解决方案。本文通过TiKV、Materialize等新一代数据库核心组件的实践案例,剖析Rust如何重塑存储引擎、查询优化…...
tree 显示到二级目录
要使用 tree 命令显示到二级目录,可以通过 -L 参数指定目录层级。具体命令如下: tree -L 2 参数说明: -L 数字:控制显示的目录深度。-L 2 表示显示到第二级目录(即当前目录下的直接子目录及其内容)。 示例输出: 复制 . ├── dir1 │ ├── file1.txt │ └─…...
UE5 在UE中创建骨骼动画
文章目录 创建动画的三种方式修改骨骼动画 创建动画的三种方式 方法一 打开一个已有的动画,左上角“创建资产/创建动画/参考姿势” 这将创建一个默认的A字形的骨骼,不建议这么做 方法二 打开一个已有的动画,左上角“创建资产/创建动画/当前…...
工业相机使用笔记
目前工业相机有多种分类方式,以下是基于不同原理和特点的类别总结: 按维度分类 2D相机: 原理:通过镜头将二维平面上的物体成像在图像传感器上,传感器上的像素点阵列捕捉物体的光信号,并转换为电信号或数字…...
深度兼容性测试和自助兼容性测试的区别,如何正确的选择?
泽众云经过几年业务快速发展,特别是泽众云兼容性测试服务已成为市场热门供应商之一,也根据用户不同需求推出了超高性价比服务,主要有深度兼容性测试和自助兼容性测试两种方式。2025年上半云真机平台的机型已升级到1000,全面覆盖了…...
Windows下安装depot_tools
一、引言 Chromium和Chromium OS使用名为depot_tools的脚本包来管理检出和审查代码。depot_tools工具集包括gclient、gcl、git-cl、repo等。它也是WebRTC开发者所需的工具集,用于构建和管理WebRTC项目。本文介绍Windows系统下安装depot_tools的方法。 二、下载depo…...
学术分享:基于 ARCADE 数据集评估 Grounding DINO、YOLO 和 DINO 在血管狭窄检测中的效果
一、引言 冠状动脉疾病(CAD)作为全球主要死亡原因之一,其早期准确检测对有效治疗至关重要。X 射线冠状动脉造影(XCA)虽然是诊断 CAD 的金标准,但这些图像的人工解读不仅耗时,还易受观察者间差异…...
NLP高频面试题(四十一)——什么是 IA3 微调?
随着大型语言模型的广泛应用,如何高效地将这些模型适配到特定任务中,成为了研究和工程实践中的重要课题。IA3(Infused Adapter by Adding and Adjusting)微调技术,作为参数高效微调的一种新颖方法,提供了在保持模型性能的同时,显著减少可训练参数数量的解决方案。 IA3 …...
STM32 模块化开发指南 · 第 3 篇 环形缓冲区 RingBuffer 模块设计与单元测试
本文是《STM32 模块化开发实战指南》第 3 篇,聚焦于“如何设计一个高性能、稳定、安全的环形缓冲区模块”。我们将从基本结构讲起,逐步完成接口定义、边界处理、API 实现与单元测试,最终实现一个可移植、线程安全、可嵌入 UART/BLE/协议模块的通用 RingBuffer。 一、RingBuf…...
软件测试岗位:IT行业中的质量守护者
在当今数字化飞速发展的IT行业,软件如同空气般无处不在,从日常的手机应用到复杂的企业级管理系统,软件的稳定性和可靠性至关重要。而软件测试岗位的从业者,就像是软件世界的质检员,精心守护着软件的质量。 一、软件测…...
单片机方案开发 代写程序/烧录芯片 九齐/应广等 电动玩具 小家电 语音开发
在电子产品设计中,单片机(MCU)无疑是最重要的组成部分之一。无论是消费电子、智能家居、工业控制,还是可穿戴设备,小家电等,单片机的应用无处不在。 单片机,简而言之,就是将计算机…...
恐龙专利及商标维权行动,已获批TRO并冻结资金
2025年3月30日,原告Shenzhen xingyin technology co.,Ltd.,现化名为Shenzhen Z Tech Co., Ltd.委托kemet律所发起维权。目前该案件已获批TRO临时禁令,涉案账户资金已被冻结,案件详情如下: 案件基本情况:起…...
【北京市小客车调控网站-注册/登录安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...
Vue 3中的 setup
Vue 3引入了Composition API,其中setup函数是这一新API的核心部分。setup函数为开发者提供了一种更灵活、更模块化的方式来组织组件逻辑。以下是关于Vue 3中setup函数的详细解释: 1. 基本概念 setup函数是组件内使用Composition API的入口点。它是一个…...
2025年实用新型专利审查周期要多久?
申请实用新型专利时,审查周期是申请人最关心的问题之一。尤其是近几年国家知识产权局不断优化流程,审查速度是否有变化?2025年申请需要等多久?本文结合最新政策和实际案例,为你全面解析! 一、实用新型专利…...
使用Python建立双缝干涉模型
引言 双缝干涉实验是物理学中经典的实验之一,它展示了光的波动性以及量子力学的奇异性。实验结果表明,当光或粒子通过两条狭缝时,它们会产生干涉现象,形成明暗相间的条纹图案。这种现象不仅说明了光的波动性,还揭示了量子力学的核心思想——粒子具有波动性。今天,我们将…...
路由交换网络专题 | 第二章 | RIP | OSPF | 路由聚合 | 路由过滤 | 静默接口
拓扑图 (1)作为企业网络边界设备,AR1 上配置什么命令,可以使 OSPF 域内所有路由都会有指向自己的默认路由。默认路由的优先级是多少。如果 OSPF 域内其他路由器同样有到达外网的路径,且优于通过 AR1 到达外网ÿ…...
python 语言 设计模式
python 语言 设计模式 设计模式是指在软件开发过程中,针对反复出现的问题所总结归纳出的通用解决方案。以下是一些常见的Python语言设计模式: 目录 python 语言 设计模式创建型模式结构型模式行为型模式创建型模式 单例模式 定义:保证一个类只有一个实例,并提供一个全局访…...
银行业务发展历史
银行业务发展历史 银行业务的发展可以追溯到古代,但其现代形式的发展可以追溯到中世纪。以下是银行业务发展的主要历史阶段: 1. 古代和中世纪时期 特点:商人提供贷款和存款服务,充当中间人转移资金,发行纸币作为支付…...
JAVA中多线程的基本用法
文章目录 一、基本概念(一)进程控制块PCB(二)并行和并发(三)进程调度1.进程的状态2.优先级3.记账信息4.上下文 (四)进程和线程1.概述2.线程为什么比进程更轻量3.进程和线程的区别和联…...
健康与好身体笔记
文章目录 保证睡眠饭后百步走,活到九十九补充钙质一副好肠胃肚子咕咕叫 健康和工作的取舍 以前对健康没概念,但是随着年龄增长,健康问题凸显出来。 持续维护该文档,健康是个永恒的话题。 保证睡眠 一是心态要好,沾枕…...
如何下载谷歌浏览器增强版(扩展支持版)
在日常浏览和工作中,Chrome 浏览器因其强大的性能和丰富的扩展插件,成为全球范围内使用最广泛的浏览器之一。然而,对于需要进行深度扩展管理或需要稳定扩展环境的用户来说,标准版的 Google Chrome 可能在某些方面仍显不足。这时候…...
TDDMS分布式存储管理系列文章--分片/分区/分桶详解
友情链接: 星环分布式存储TDDMS大揭秘(一)分布式存储技术推出背景以及当前存在的挑战TDDMS是什么 前情提要 通过上个系列的文章我们了解到了各节点数据副本间通过一致性算法确保每次写入在响应客户端请求之前至少被多数节点(N/2…...
Spring Boot(九十):集成SSE (Server-Sent Events) 服务器实时推送
1 SSE简介 Server-sent Events(SSE) 是一种基于 HTTP 协议的服务器推送技术,它允许服务器主动向客户端发送数据。与 WebSocket 不同,SSE 是单向通信,即服务器可以主动向客户端推送数据,而客户端只能接收数据。 2 SSE特点 单向通信:SSE 是服务器向客户端的单向推送,客户…...
ubuntu22.04安装ROS2 humble
参考: https://zhuanlan.zhihu.com/p/702727186 前言: 笔记本安装了ubuntu20.04安装ros一直失败,于是将系统升级为ununut22.04,然后安装ros,根据上面的教程,目前看来是有可能成功的。 系统升级为ununut…...