Modbus RTU ---> Modbus TCP透传技术实现(Modbus透传、RS485透传、RTU透传)分站代码实现、协议转换器
文章目录
- Modbus RTU到Modbus TCP透传技术实现
- 1. 透传技术概述
- 1.1 透传基本原理
- - 协议帧格式转换
- - 地址映射与管理
- - 通信时序适配
- - 错误检测与处理
- 2. 透传网关硬件架构
- 2.1 典型硬件结构
- - 微控制器/处理器(ARM、STM32等)
- - RS-485/RS-232收发器
- - 以太网控制器(如W5500)
- - 电源管理模块
- - 状态指示灯和配置接口
- 2.2 接口设计
- - **串行接口**:RS-485/RS-232,支持多波特率配置
- - **网络接口**:RJ45以太网接口,支持10/100Mbps
- - **配置接口**:串口调试/Web界面/按键配置
- 3. 协议转换核心技术
- 3.1 报文结构转换
- 转换规则:
- 1. 生成MBAP头部(事务标识符、协议标识符、长度、单元标识符)
- 2. 将RTU帧中的功能码和数据部分复制到TCP帧
- 3. 移除CRC校验(TCP层已有错误检测机制)
- 3.2 地址映射策略
- 3.2.1 单元标识符映射
- - **直接映射法**:Unit ID = 从站地址
- - **表映射法**:通过映射表将从站地址转换为自定义Unit ID
- - **统一标识符法**:所有设备使用同一Unit ID,通过数据区分设备
- 3.3 时序管理
- - RTU帧之间的3.5个字符时间间隔
- - TCP通信的延迟和不确定性
- - 接收超时与重传机制
- 4. 透传实现代码分析
- 4.1 RTU到TCP转换核心代码
- 4.2 TCP到RTU转换核心代码
- 5. 通信管理
- 5.1 TCP连接管理
- 5.2 RTU通信管理
- 6. 缓冲区和数据流管理
- 6.1 缓冲区设计
- 6.2 数据流处理
- 7. 异常处理与错误恢复
- 7.1 错误码定义
- 7.2 异常响应处理
- 8. 透传网关配置管理
- 8.1 配置参数结构
- 8.2 配置持久化
- 9. 实际应用优化
- 9.1 性能优化
- - **零拷贝技术**:减少数据复制操作
- - **轮询优化**:使用select/epoll等机制提高I/O效率
- - **预分配缓冲区**:避免动态内存分配开销
- 9.2 可靠性提升
- 10. 实际部署案例
- 1. **部署环境**:
- 2. **网关配置**:
- 3. **性能指标**:
Modbus RTU到Modbus TCP透传技术实现
1. 透传技术概述
透传技术是将Modbus RTU数据封装到Modbus TCP报文中进行传输的桥梁技术,使传统的串行设备能够接入以太网环境,实现远距离通信和更灵活的网络拓扑。
1.1 透传基本原理
透传技术本质是协议转换过程,需要处理以下关键环节:
- 协议帧格式转换
- 地址映射与管理
- 通信时序适配
- 错误检测与处理
2. 透传网关硬件架构
2.1 典型硬件结构
透传网关通常包含以下硬件组件:
- 微控制器/处理器(ARM、STM32等)
- RS-485/RS-232收发器
- 以太网控制器(如W5500)
- 电源管理模块
- 状态指示灯和配置接口
2.2 接口设计
- 串行接口:RS-485/RS-232,支持多波特率配置
- 网络接口:RJ45以太网接口,支持10/100Mbps
- 配置接口:串口调试/Web界面/按键配置
3. 协议转换核心技术
3.1 报文结构转换
Modbus RTU:
+--------+--------+--------+--------+
| 从站地址 | 功能码 | 数据域 | CRC校验 |
+--------+--------+--------+--------+Modbus TCP:
+----------------+--------+--------+
| MBAP头部(7字节) | 功能码 | 数据域 |
+----------------+--------+--------+
转换规则:
1. 生成MBAP头部(事务标识符、协议标识符、长度、单元标识符)
2. 将RTU帧中的功能码和数据部分复制到TCP帧
3. 移除CRC校验(TCP层已有错误检测机制)
3.2 地址映射策略
3.2.1 单元标识符映射
将RTU帧中的从站地址映射为TCP帧中的单元标识符(Unit ID),有以下几种方式:
- 直接映射法:Unit ID = 从站地址
- 表映射法:通过映射表将从站地址转换为自定义Unit ID
- 统一标识符法:所有设备使用同一Unit ID,通过数据区分设备
3.3 时序管理
RTU通信具有严格的时序要求,而TCP为无时序协议,需要处理:
- RTU帧之间的3.5个字符时间间隔
- TCP通信的延迟和不确定性
- 接收超时与重传机制
4. 透传实现代码分析
4.1 RTU到TCP转换核心代码
// RTU帧转TCP帧
int ConvertRTUtoTCP(uint8_t* rtuFrame, int rtuLen, uint8_t* tcpFrame)
{static uint16_t transactionId = 0;// 检查RTU帧长度有效性if (rtuLen < 4) return -1; // 至少包含地址、功能码和CRC// 验证RTU帧CRCuint16_t crc = CalculateCRC(rtuFrame, rtuLen - 2);uint16_t frameCrc = (rtuFrame[rtuLen-2] | (rtuFrame[rtuLen-1] << 8));if (crc != frameCrc) return -2; // CRC错误// 构建MBAP头tcpFrame[0] = (transactionId >> 8) & 0xFF; // 事务标识符高字节tcpFrame[1] = transactionId & 0xFF; // 事务标识符低字节tcpFrame[2] = 0x00; // 协议标识符高字节(Modbus=0)tcpFrame[3] = 0x00; // 协议标识符低字节tcpFrame[4] = ((rtuLen - 3) >> 8) & 0xFF; // 长度高字节(不含CRC)tcpFrame[5] = (rtuLen - 3) & 0xFF; // 长度低字节tcpFrame[6] = rtuFrame[0]; // 单元标识符(从站地址)// 复制功能码和数据(去除地址和CRC)memcpy(&tcpFrame[7], &rtuFrame[1], rtuLen - 3);// 更新事务标识符transactionId++;// 返回TCP帧长度return rtuLen - 2 + 7; // RTU长度 - CRC + MBAP头
}
4.2 TCP到RTU转换核心代码
// TCP帧转RTU帧
int ConvertTCPtoRTU(uint8_t* tcpFrame, int tcpLen, uint8_t* rtuFrame)
{// 检查TCP帧长度有效性if (tcpLen < 8) return -1; // MBAP头(7) + 功能码(1)// 验证MBAP头中的长度字段uint16_t length = (tcpFrame[4] << 8) | tcpFrame[5];if (length != tcpLen - 6) return -2; // 长度字段错误// 提取单元标识符作为RTU的从站地址rtuFrame[0] = tcpFrame[6];// 复制功能码和数据部分memcpy(&rtuFrame[1], &tcpFrame[7], tcpLen - 7);// 计算并添加CRCuint16_t crc = CalculateCRC(rtuFrame, tcpLen - 7 + 1);rtuFrame[tcpLen - 7 + 1] = crc & 0xFF;rtuFrame[tcpLen - 7 + 2] = (crc >> 8) & 0xFF;// 返回RTU帧长度return tcpLen - 7 + 3; // TCP数据长度 - MBAP + 地址 + CRC
}
5. 通信管理
5.1 TCP连接管理
typedef struct {int socketFd;uint8_t unitId;time_t lastActive;bool isActive;
} TCPConnection;TCPConnection connections[MAX_CONNECTIONS];// 查找或创建连接
int GetConnection(uint8_t unitId) {int oldestIdx = -1;time_t oldestTime = time(NULL);// 查找现有连接for (int i = 0; i < MAX_CONNECTIONS; i++) {if (connections[i].isActive && connections[i].unitId == unitId) {connections[i].lastActive = time(NULL);return i;}// 记录最旧的非活跃连接if (!connections[i].isActive && connections[i].lastActive < oldestTime) {oldestIdx = i;oldestTime = connections[i].lastActive;}}// 没有找到现有连接,使用最旧的非活跃连接if (oldestIdx >= 0) {InitConnection(&connections[oldestIdx], unitId);return oldestIdx;}return -1; // 无可用连接
}
5.2 RTU通信管理
// RTU通信超时设置
typedef struct {uint32_t charTimeout; // 字符间超时(基于波特率)uint32_t frameTimeout; // 帧超时(3.5个字符时间)uint8_t maxRetry; // 最大重试次数
} RTUTimeoutConfig;// 计算字符超时时间
void CalculateTimeouts(uint32_t baudRate, RTUTimeoutConfig* config) {// 1个字符时间(毫秒) = (1000 * 10) / 波特率// 10位 = 起始位(1) + 数据位(8) + 停止位(1)float charTime = (1000.0 * 10) / baudRate;config->charTimeout = (uint32_t)(charTime * 1.5); // 1.5个字符时间config->frameTimeout = (uint32_t)(charTime * 3.5); // 3.5个字符时间
}
6. 缓冲区和数据流管理
6.1 缓冲区设计
typedef struct {uint8_t data[BUFFER_SIZE];uint16_t head;uint16_t tail;uint16_t count;pthread_mutex_t mutex;
} CircularBuffer;// 初始化缓冲区
void InitBuffer(CircularBuffer* buffer) {buffer->head = 0;buffer->tail = 0;buffer->count = 0;pthread_mutex_init(&buffer->mutex, NULL);
}// 写入数据
bool WriteBuffer(CircularBuffer* buffer, uint8_t* data, uint16_t len) {pthread_mutex_lock(&buffer->mutex);if (buffer->count + len > BUFFER_SIZE) {pthread_mutex_unlock(&buffer->mutex);return false; // 缓冲区空间不足}for (uint16_t i = 0; i < len; i++) {buffer->data[buffer->tail] = data[i];buffer->tail = (buffer->tail + 1) % BUFFER_SIZE;buffer->count++;}pthread_mutex_unlock(&buffer->mutex);return true;
}
6.2 数据流处理
多线程处理模型示例:
// 线程函数:处理RTU到TCP的数据转发
void* RTUtoTCPThread(void* arg) {GatewayContext* ctx = (GatewayContext*)arg;uint8_t rtuBuffer[MAX_RTU_FRAME_SIZE];uint8_t tcpBuffer[MAX_TCP_FRAME_SIZE];int rtuLen, tcpLen;while (!ctx->stopFlag) {// 从RTU接收数据rtuLen = ReceiveRTUFrame(ctx->serialFd, rtuBuffer);if (rtuLen > 0) {// 转换为TCP帧tcpLen = ConvertRTUtoTCP(rtuBuffer, rtuLen, tcpBuffer);if (tcpLen > 0) {// 获取TCP连接int connIdx = GetConnection(rtuBuffer[0]);if (connIdx >= 0) {// 发送TCP数据SendTCPFrame(ctx->connections[connIdx].socketFd, tcpBuffer, tcpLen);}}}usleep(1000); // 避免CPU占用过高}return NULL;
}
7. 异常处理与错误恢复
7.1 错误码定义
typedef enum {ERR_NONE = 0,ERR_CRC_FAILED, // CRC校验失败ERR_FRAME_TIMEOUT, // 帧接收超时ERR_BUFFER_OVERFLOW, // 缓冲区溢出ERR_TCP_DISCONNECTED, // TCP连接断开ERR_INVALID_RESPONSE, // 无效响应ERR_DEVICE_BUSY, // 设备忙ERR_MODBUS_EXCEPTION // Modbus异常响应
} ErrorCode;
7.2 异常响应处理
// 处理Modbus异常
void HandleModbusException(uint8_t* frame, ErrorCode error) {uint8_t funcCode = frame[1];switch (error) {case ERR_MODBUS_EXCEPTION:// 已经是异常响应,不需处理break;case ERR_DEVICE_BUSY:frame[1] = funcCode | 0x80; // 设置异常标志位frame[2] = 0x06; // 从站设备忙break;case ERR_INVALID_RESPONSE:frame[1] = funcCode | 0x80;frame[2] = 0x03; // 非法数据值break;default:frame[1] = funcCode | 0x80;frame[2] = 0x04; // 从站设备故障break;}
}
8. 透传网关配置管理
8.1 配置参数结构
typedef struct {// RTU参数uint32_t baudRate; // 波特率uint8_t dataBits; // 数据位uint8_t stopBits; // 停止位uint8_t parity; // 校验位uint32_t timeout; // 超时时间(毫秒)// TCP参数char serverIP[16]; // 服务器IPuint16_t serverPort; // 服务器端口uint16_t localPort; // 本地端口uint16_t maxConnections; // 最大连接数uint32_t tcpTimeout; // TCP超时时间// 地址映射bool useDirectMapping; // 是否使用直接映射AddressMapEntry addressMap[MAX_DEVICES]; // 地址映射表
} GatewayConfig;
8.2 配置持久化
// 保存配置到文件
bool SaveConfig(const char* filename, GatewayConfig* config) {FILE* file = fopen(filename, "wb");if (!file) return false;fwrite(config, sizeof(GatewayConfig), 1, file);fclose(file);return true;
}// 从文件加载配置
bool LoadConfig(const char* filename, GatewayConfig* config) {FILE* file = fopen(filename, "rb");if (!file) return false;size_t read = fread(config, sizeof(GatewayConfig), 1, file);fclose(file);return (read == 1);
}
9. 实际应用优化
9.1 性能优化
- 零拷贝技术:减少数据复制操作
- 轮询优化:使用select/epoll等机制提高I/O效率
- 预分配缓冲区:避免动态内存分配开销
9.2 可靠性提升
// 看门狗实现
void* WatchdogThread(void* arg) {GatewayContext* ctx = (GatewayContext*)arg;time_t lastActivity = time(NULL);while (!ctx->stopFlag) {time_t now = time(NULL);// 检查活动状态if (now - lastActivity > WATCHDOG_TIMEOUT) {// 记录事件LogEvent("Watchdog timeout detected");// 重置设备ResetDevice(ctx);lastActivity = now;}// 检查连接状态for (int i = 0; i < ctx->config.maxConnections; i++) {if (ctx->connections[i].isActive) {if (now - ctx->connections[i].lastActive > TCP_CONN_TIMEOUT) {// 关闭超时连接CloseConnection(&ctx->connections[i]);LogEvent("Connection timeout: %d", i);}}}sleep(1);}return NULL;
}
10. 实际部署案例
某工厂自动化系统实现:
1. 部署环境:
10个Modbus RTU传感器和执行器连接到透传网关,网关通过企业以太网与SCADA系统相连
2. 网关配置:
- RTU: 9600bps, 8N1, RS-485
- TCP: 内网固定IP, 端口502
- 直接地址映射
3. 性能指标:
- 响应时间:小于100ms
- 稳定性:连续运行时间>6个月
- 每分钟处理300+次数据交换
通过该透传方案,成功实现了传统设备的网络化改造,为工业物联网升级奠定基础。
相关文章:
Modbus RTU ---> Modbus TCP透传技术实现(Modbus透传、RS485透传、RTU透传)分站代码实现、协议转换器
文章目录 Modbus RTU到Modbus TCP透传技术实现1. 透传技术概述1.1 透传基本原理- 协议帧格式转换- 地址映射与管理- 通信时序适配- 错误检测与处理 2. 透传网关硬件架构2.1 典型硬件结构- 微控制器/处理器(ARM、STM32等)- RS-485/RS-232收发器- 以太网控制器(如W5500)- 电源管理…...
Flask(三)路由与视图函数
在 Flask 中,路由 (Route) 是将 URL 地址映射到特定的视图函数 (View Function) 的机制。视图函数处理用户请求,并返回 HTTP 响应。理解路由和视图函数是构建 Flask 应用的基础。 3.1 路由的基本概念 Flask 使用 app.route() 装饰器来定义路由。以下是…...
mysql 磐维(opengauss)tidb误删数据之高级恢复
Mysql参考: Mysql 8.0 XtraBackupMysqlbinlog 完全恢复 - 墨天轮 Mysql 8.0 XtraBackupMysqlbinlog 完全恢复[TOC]# 一、安装mysql 8.0.19## 1.1https://www.modb.pro/db/509223MySQL 的全量备份、增量备份与 Binlog 时间点恢复_mysqlbinlog自动备份吗-CSDN博客文章…...
常见框架漏洞(一)----Thinkphp(TP)
Thinkphp框架介绍: ThinkPHP是为了简化企业级应⽤开发和敏捷WEB应⽤开发⽽诞⽣的,是⼀个快速、兼容⽽ 且简单的轻量级国产PHP开发框架,诞⽣于2006年初,原名FCS,2007年元旦正式更名为 ThinkPHP,遵循Apache…...
Git 使用指南:从设置用户信息到项目提交的全流程教程(持续更新)
一、设置 Git 用户信息 1.全局设置(适用于所有 Git 仓库): git config --global user.name "Your Name" git config --global user.email youexample.com 2.仅针对当前仓库设置(如果您只想为当前项目设置࿰…...
Json在扩展属性xdata中的应用实例——cad 二次开发c#
以下是一个使用AutoCAD C#.NET API实现你需求的示例代码,代码实现了提示用户选择一个实体,将一些字符串变量及其对应的值组成JSON格式数据存储到实体的扩展数据(XData)中,并在弹出窗口中显示该实体的所有扩展数据信息。…...
Unity Animation的其中一种运用方式
Animation是Unity的旧的动画系统,先说目的,其使用是为了在UI中播放动效,并且在动效播放结束后接自定义事件而设计的 设计的关键点在于,这个脚本不是通过Animation直接播放动画片段,而是通过修改AnimationState的nor…...
C++ 的基本内置类型(十二)
C 作为一门强大的编程语言,其内置类型是开发者必须掌握的基础。本文将详细介绍 C 的基本内置类型,包括算术类型和空类型,探讨它们的特性、尺寸以及在机器上的实现方式。 一、 基本内置类型概述 C 定义了一套基本数据类型,主要包…...
Android设计模式之单例模式
一、定义:确保一个类只有一个实例,并且自动实例化,并向整个系统提供这个实例。 二、使用场景:避免重复创建对象,过多消耗系统资源。 三、使用方式 3.1饿汉式:类加载时立即初始化,线程安全&…...
随笔(1)
1、解除切屏限制命令 document.body.onblur null2、vue3 getCurrentInstance import { getCurrentInstance } from vue const {proxy} getCurrentInstance() proxy.mittBus.emit(message,xxxx)3、 自定义双向绑定,modelValue 就是对应输入框的值 emit(update:mo…...
系统与网络安全------网络应用基础(3)
资料整理于网络资料、书本资料、AI,仅供个人学习参考。 路由器 认识路由器 负责在不同网络之间转发数据的设备 路由器决定到达目标的路径 路由器也为直连网络的主机充当”网关“角色 路由器是实现网络互连的最核心设备 工作原理 每台路由器维护一份路由表&…...
Java 基于微信小程序的开放实验室预约管理系统
博主介绍:✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不…...
Linux内核NIC网卡驱动实战案例分析
以下Linux 内核模块实现了一个虚拟网络设备驱动程序,其作用和意义如下: 1. 作用 (1)创建虚拟网络设备对 驱动程序动态创建了两个虚拟网络设备(nic_dev[0]和nic_dev[1]),模拟物理网卡的功能。这两…...
R 基础语法
R 基础语法 引言 R 是一种针对统计计算和图形表示而设计的编程语言和环境。它广泛应用于统计学、生物信息学、数据挖掘等领域。本文将为您介绍 R 语言的基础语法,帮助您快速上手。 R 的基本结构 R 语言的基本结构包括:变量、数据类型、运算符、控制结构、函数等。 变量 …...
JDK 24 发布,新特性解读!
一、版本演进与技术格局新动向 北京时间3月20日,Oracle正式发布Java SE 24。作为继Java 21之后的第三个非LTS版本,其技术革新力度远超预期——共集成24项JEP提案,相当于Java 22(12项)与Java 23(12项&#…...
在 Qt 中,不带参数或整形的参选的信号能够从 std::thread 发送成功,而带枚举离线的信号却发送失败
在 Qt 中,不带参数或整形的参选的信号能够从 std::thread 发送成功,而带枚举离线的信号却发送失败 当信号和槽在不同线程时,默认使用 队列连接(Qt::QueuedConnection),信号会被放入接收线程的事件队列&…...
慧通测控汽车智能座舱测试技术
一、引言 随着科技的飞速发展,汽车正从单纯的交通工具向智能化移动空间转变。智能座舱作为这一转变的核心体现,融合了多种先进技术,为用户带来前所未有的驾驶体验。从简单的信息娱乐系统到高度集成的人机交互、智能驾驶辅助以及车辆状态监测…...
【CSS】CSS 使用全教程
CSS 使用全教程 介绍 CSS(层叠样式表,Cascading Style Sheets)是一种样式表语言,用于描述 HTML 或 XML 文档的布局和外观,它允许开发者将文档的内容结构与样式表现分离,通过定义一系列的样式规则来控制网页…...
【Linux知识】RPM软件包安装命令行详细说明
文章目录 概述安装软件包升级软件包卸载软件包查询软件包信息验证软件包从软件包中提取文件注意事项 概述 rpm(Red Hat Package Manager)是红帽系 Linux 发行版(如 Red Hat、CentOS、Fedora 等)用于管理软件包的工具,…...
SpringBoot3.0不建议使用spring.factories,使用AutoConfiguration.imports新的自动配置方案
文章目录 一、写在前面二、使用imports文件1、使用2、示例比对3、完整示例 参考资料 一、写在前面 spring.factories是一个位于META-INF/目录下的配置文件,它基于Java的SPI(Service Provider Interface)机制的变种实现。 这个文件的主要功能是允许开发者声明接口的…...
c++项目-KV存储-模仿redis实现kv键值对存储的基本功能。
KV存储引擎的技术解析:数组、哈希与红黑树实现及其在网络I/O中的应用。 内容概要:本文档深入介绍了基于数组、哈希表和红黑树的键值存储引擎的设计与实现。文档首先阐述了系统的总体架构与类图关系,之后分别对底层存储结构进行了详细解释&am…...
docker ssh远程连接
目录 操作命令: 确保 SSH 配置允许 root 登录: docker提交: 操作命令: # 进入容器 docker exec -ti lbg04 /bin/bash# 更新包管理并安装 SSH 服务(Ubuntu/Debian 示例) apt-get update apt-get install…...
边缘计算场景下的分布式推理系统架构设计
一、边缘节点推理优化 1.1 模型轻量化技术矩阵 1.2 TensorRT加速配置示例 # 使用TensorRT优化YOLOv8builder trt.Builder(TRT_LOGGER)network builder.create_network()parser trt.OnnxParser(network, TRT_LOGGER)with open("yolov8s.onnx", "rb") a…...
css基础-浮动
一、浮动是什么? 比喻:就像泳池里的救生圈 原始用途:让文字环绕图片(像杂志排版)意外发展:被用来做页面布局(像用救生圈搭浮桥) 二、浮动怎么产生的? 场景还原&#…...
Linux TTY设备汇总
目录 1. tty(终端设备统称) 2. ptm(伪终端主设备)与pts(伪终端从设备) 3. ttys(串行端口终端) 4. ttyACM(USB CDC ACM设备) 5. ttyGS(USB Gadget Serial设备) 主要联系 典型应用场景 TTY_CORE: drivers/tty/tty_io.c:tty_register_driver…...
Android studio组合教程--做出一个类似于QQ的登录页面
之前我们学过了html与Android的开发,以及各种组件的学习,这次我们做一个完整向的登录页面,作为一次大作业。 注意 里面的一图片可以自由发挥,但要注意文件路径保持准确,这里给出参考路径: 背景路径&…...
iPhone 16 Plus :凉凉了
大屏就是生产力,这句话就像思想钢印一样,深入人心。 但苹果用户是个例外,根据内行人的爆料,iPhone 16 Plus 彻底凉凉了,难怪它会是最后一代Plus。 根据知名博主数码闲聊站透露,截止3 月 9 号,i…...
【MySQL报错】:Column count doesn’t match value count at row 1
MySQL报错:Column count doesn’t match value count at row 1 意思是存储的数据与数据库表的字段类型定义不相匹配. 由于类似 insert 语句中,前后列数不等造成的 主要有3个易错点: 要传入表中的字段数和values后面的值的个数不相等。 由于类…...
2025 polarctf春季个人挑战赛web方向wp
来个弹窗 先用最基础的xss弹窗试一下 <script>alert("xss")</script>没有内容,猜测过滤了script,双写绕过一下 <scrscriptipt>alert("xss")</scscriptript>background 查看网页源代码 查看一下js文件 类…...
Midscene.js自然语言驱动的网页自动化全指南
一、概述 网页自动化在数据抓取、UI 测试和业务流程优化中发挥着重要作用。然而,传统工具如 Selenium 和 Puppeteer 要求用户具备编程技能,编写复杂的选择器和脚本维护成本高昂。Midscene.js 通过自然语言接口革新了这一领域,用户只需描述任…...
PDF与Markdown的量子纠缠:一场由VLM导演的文档界奇幻秀
缘起:当格式界的"泰坦尼克号"撞上"黑客帝国" 某个月黑风高的夜晚,在"二进制酒吧"的霓虹灯下: PDF(西装革履地晃着威士忌): “我的每一页都像瑞士手表般精密,连华尔街的秃鹫都为我倾倒!” Markdown(穿着带洞的拖鞋): “得了吧老古董!…...
Spring Boot JSON序列化深度管控:忽略指定字段+Jackson扩展策略破解双向实体循环引用问题
一、JsonIgnore的核心原理与工作机制 1. 注解作用原理 JsonIgnore是Jackson库的核心注解之一,其工作原理基于 Jackson的AnnotationIntrospector机制。在序列化/反序列化过程中,Jackson会扫描Java对象的所有字段和方法上的注解。当检测到JsonIgnore时&a…...
msvcp140.dll是什么文件?修复丢失msvcp140.dll的方法指南
当计算机显示"msvcp140.dll未找到"的报错信息时,这实际反映了Windows系统运行机制中的一个关键环节出现断链。作为Microsoft Visual C可再发行组件包的核心动态链接库,msvcp140.dll承担着程序与系统资源之间的桥梁作用,特别是在处理…...
ES集群的部署
实验步骤 实验目的: 验证ES集群的容错性、扩展性数据分布与查询性能优化。 环境准备 1、准备两台服务器 服务器 1、10.1.1.20 cpu 2核 内存:4G 硬盘100G 2、10.1.1.21 cpu 2核 内存:4G 硬盘100G 2、修改两台静态ip 3、关闭防…...
resetForm() 方法用于重置表单
resetForm() 方法是 Vue.js 中用于重置表单的一个常见操作。下面是对这段代码的详细解析: 1. 代码作用 resetForm() 方法的作用是重置表单,将表单中的所有输入字段恢复到初始状态(通常是清空或恢复到默认值)。 2. 代码解析 re…...
Java后端API限流秘籍:高并发的防护伞与实战指南
目录导航 📜 🛡️ 为什么需要API限流?🧠 主流限流算法大解析👩💻 阿里巴巴的限流实践📏 四大黄金定律🤼 限流策略组合拳🏆 限流场景实战💻 技术实现方案🌟 最佳实践分享📈 结语与展望📚 推荐阅读 1. 🛡️ 为什么需要API限流? 在高并发环境中,未…...
团体协作项目总结Git
使用Git开放时候发现本地, 有些代码并没有被拉取到本地仓库, 又不想再commit一次, 这时候我就想到了 git commit --amend 合并提交 git commit --amend 修改git提交记录用法详解 可以将本次提交记录合并到上一次合并提交 git commit --amendgit rebase -i master^^ // 假设我…...
mysql 入门
1.已经下载过却卸载不干净?注册表清理不到位? 使用greek绿色版 强力卸载,可以一键卸载注册表里的信息。 2.如何启动mysql服务? 以管理员方式启动cmd 输入 net start mysql80 如何停止? net stop mysql80 2.将mysql客…...
1.基于TCP的简单套接字服务器实现
目录 1. TCP通信流程 2. 服务器端的通信流程 2.1 创建用于监听的套接字 2.2 绑定本地IP地址和端口 2.3 设置监听 2.4 等待接受客户端的连接请求 2.5 与客户端进行通信 2.6 客户端连接服务器 3.代码实现 client.cpp server.cpp 运行方式 在本文中,我们将…...
MantisBT在Windows10上安装部署详细步骤
MantisBT 是一款基于 Web 的开源缺陷跟踪系统,以下是在 Windows 10 上安装部署 MantisBT 的详细步骤: 1. 安装必要的环境 MantisBT 是一个基于 PHP 的 Web 应用程序,因此需要安装 Web 服务器(如 Apache)、PHP 和数据…...
zookeepernacoskafka之间的联系
一、ZooKeeper与Kafka的协同工作原理 1. 核心关系:Kafka对ZooKeeper的依赖 在Kafka 2.8版本之前,ZooKeeper是Kafka集群的“大脑”,负责管理集群元数据、协调节点状态和故障恢复。两者的协同主要通过以下关键机制实现: Broker注册…...
【QT】 布局器
参考博客:https://blog.csdn.net/Fdog_/article/details/107522283 目录 布局管理器概念常见的布局管理器及特点🔵QHBoxLayout水平布局🔵QVBoxLayout垂直布局 🔵QGridLayout网格布局 🔵QFormLayout表单布局 QT 高级布…...
力扣45.跳跃游戏
45. 跳跃游戏 II - 力扣(LeetCode) 代码区: #include<vector> class Solution {public:int jump(vector<int>& nums) {int ans[10005] ;memset(ans,1e4,sizeof(ans));ans[0]0;for(int i0;i<nums.size();i){for(int j1;j…...
【蓝桥杯】真题 路径(数论+dp)
思路 求最小公倍数LCM问题很好求,这里看似是求图最短路径,实际上由于只有[i,i21]之间存在路径,所以用线性dp效率更高,当然用bfs,dijstra,floyed也可,毕竟是填空题。 code def gcd(a,b):if a …...
敏捷需求分析之INVEST原则
INVEST原则是什么 INVEST 是用户故事的六个核心标准,由敏捷教练 Bill Wake 提出,用于确保用户故事具备可执行性和价值导向性。 1. I - Independent(独立的) 含义:用户故事应独立于其他故事,避免依赖关系。问题:若故事 A 必须等待故事 B 完成才能开发,会导致进度阻塞。…...
Apache Flink技术原理深入解析:任务执行流程全景图
前言 本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 思维导图 📌 引言 Apache Flink 作为一款高性能的分布式流处理引擎,其内部执行机制精妙而复杂。本文将…...
UE5小石子阴影在非常近距离才显示的问题
Unreal中采用LandscapeGrass生成的地形,在MovieRenderQueue中渲染时阴影显示距离有问题,在很近的时候才会有影子,怎么解决? 地面上通过grass生成的小石子的阴影只能在很近的时候才能显示出来,需要如下调整 r.Shadow.R…...
WebAssembly实践,性能也有局限性
个人博客原文地址 WebAssembly(简称 wasm) 是一种旨在突破 Web 性能瓶颈的技术方案。它由 W3C 官方推动,并且得到了主流浏览器的广泛支持。它的核心思想是通过运行其他高性能编程语言(比如 C、C、Rust 等)来实现复杂功…...
第一天学爬虫
阅读提示:我今天才开始尝试爬虫,写的不好请见谅。 一、准备工具 requests库:发送HTTP请求并获取网页内容。BeautifulSoup库:解析HTML页面并提取数据。pandas库:保存抓取到的数据到CSV文件中。 二、爬取步骤 发送请求…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(11)
1.问题描述: 鸿蒙push右侧图表没有正常展示。 解决方案: .jpg格式文件,头信息必须是这个“jpg:ffd8”。 2.问题描述: 安卓端App在开发者平台申请了Android应用的通知消息自分类权益,鸿蒙应用的自分类权…...