Mosquitto MQTT库实战指南
目录
- 1. MQTT协议简介
- 2. Mosquitto概述
- 3. 开源MQTT实现对比
- 4. 为什么选择Mosquitto
- 5. Mosquitto的交叉编译
- 6. MQTT发布订阅实战
- 7. 进阶应用与最佳实践
- 8. 总结
1. MQTT协议简介
MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级通信协议,专为资源受限的设备和低带宽、高延迟或不可靠的网络设计。由于其简单性和灵活性,MQTT已成为物联网(IoT)领域中最受欢迎的通信协议之一。
MQTT的核心特性
- 轻量级:协议开销小,最小只需2字节头部
- 发布/订阅模式:解耦消息发布者和订阅者
- 可靠性:提供三种服务质量级别(QoS)
- 保留消息:允许新订阅者接收最新状态
- 持久会话:支持客户端断线重连
2. Mosquitto概述
Eclipse Mosquitto是一个实现了MQTT协议3.1和3.1.1版本的开源消息代理软件。它由Eclipse Foundation维护,使用C语言编写,具有轻量级、低资源消耗和高性能的特点,特别适合在嵌入式设备和资源受限环境中使用。
Mosquitto作为一个完整的MQTT解决方案,包含了:
- mosquitto:MQTT服务器(代理)
- mosquitto_pub:MQTT发布客户端工具
- mosquitto_sub:MQTT订阅客户端工具
- libmosquitto:C语言实现的客户端库,可用于开发自定义应用
Mosquitto于2009年由Roger Light开发,2013年加入Eclipse基金会,目前最新稳定版本为2.0.15(截至2023年),已全面支持MQTT 5.0标准。
3. 开源MQTT实现对比
在选择MQTT库时,我们需要考虑多种因素,包括性能、资源占用、稳定性、功能完整性和社区活跃度等。下面是几种主流开源MQTT实现的对比:
实现名称 | 开发语言 | 许可证 | MQTT版本支持 | 资源占用 | 特点 |
---|---|---|---|---|---|
Mosquitto | C | EPL/EDL | 3.1, 3.1.1, 5.0 | 极低 | 轻量级、高效、成熟稳定 |
EMQX | Erlang | Apache 2.0 | 3.1, 3.1.1, 5.0 | 中等 | 高性能、可扩展、企业级 |
VerneMQ | Erlang | Apache 2.0 | 3.1, 3.1.1, 5.0 | 中等 | 分布式、高可用性 |
HiveMQ | Java | 商业/社区版 | 3.1, 3.1.1, 5.0 | 高 | 企业级、集群支持 |
Moquette | Java | Apache 2.0 | 3.1, 3.1.1 | 中等 | 嵌入友好 |
各MQTT实现支持的QoS级别:
实现名称 | QoS 0 | QoS 1 | QoS 2 |
---|---|---|---|
Mosquitto | ✅ | ✅ | ✅ |
EMQX | ✅ | ✅ | ✅ |
VerneMQ | ✅ | ✅ | ✅ |
HiveMQ | ✅ | ✅ | ✅ |
Moquette | ✅ | ✅ | ✅ |
4. 为什么选择Mosquitto
在众多MQTT实现中,Mosquitto具有以下优势:
4.1 资源占用低
Mosquitto的内存和CPU使用率极低,使其非常适合资源受限的环境:
- 空闲状态下仅占用约3MB内存
- 单核处理器上能处理数万连接
- 适合部署在边缘设备、嵌入式系统和物联网网关
4.2 成熟稳定
Mosquitto有十多年的开发历史,经过大量生产环境验证:
- 广泛的社区支持和丰富的文档
- 定期更新和活跃的维护
- 严格遵循MQTT标准
4.3 易于集成
提供了多种语言的客户端库和简单的API:
- C/C++库(libmosquitto)
- 丰富的命令行工具
- 支持通过各种编程语言的绑定使用
4.4 安全特性
- TLS/SSL加密支持
- 用户名/密码认证
- ACL访问控制列表
- 传输数据加密
4.5 跨平台
Mosquitto支持多种操作系统平台:
- Linux
- Windows
- macOS
- 嵌入式系统(如树莓派、ESP32等)
5. Mosquitto的交叉编译
在嵌入式开发中,我们常需要在一个平台上编译代码,然后在另一个平台上运行,这就是交叉编译。下面介绍如何为ESP32等嵌入式平台交叉编译Mosquitto。
5.1 准备交叉编译环境
首先,我们需要安装必要的交叉编译工具链:
# 安装交叉编译工具链(以ARM为例)
sudo apt-get install gcc-arm-linux-gnueabihf
sudo apt-get install g++-arm-linux-gnueabihf
对于ESP32平台,我们需要安装ESP-IDF:
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh
. ./export.sh
5.2 交叉编译Mosquitto
5.2.1 获取Mosquitto源码
git clone https://github.com/eclipse/mosquitto.git
cd mosquitto
5.2.2 配置交叉编译参数
创建一个配置文件config.mk
:
# 指定交叉编译工具链
CC=arm-linux-gnueabihf-gcc
CXX=arm-linux-gnueabihf-g++
STRIP=arm-linux-gnueabihf-strip# 禁用不必要的功能,减小二进制大小
WITH_DOCS=no
WITH_BROKER=no
WITH_CLIENTS=yes
WITH_APPS=no
WITH_PLUGINS=no
WITH_LIB_CPP=no
WITH_THREADING=yes
WITH_SOCKS=no
WITH_TLS=no
WITH_TLS_PSK=no
WITH_EC=no
5.2.3 执行编译
make -j4
5.2.4 ESP32专用编译
对于ESP32平台,可以使用ESP-IDF的组件机制:
# 创建一个组件目录
mkdir -p components/mosquitto
cd components/mosquitto# 准备源码和CMakeLists.txt
git clone --depth 1 https://github.com/eclipse/mosquitto.git src
创建一个CMakeLists.txt
文件:
idf_component_register(SRCS"src/lib/mosquitto.c""src/lib/actions.c""src/lib/callbacks.c""src/lib/connect.c""src/lib/handle_auth.c""src/lib/handle_connack.c""src/lib/handle_disconnect.c""src/lib/handle_ping.c""src/lib/handle_pubackcomp.c""src/lib/handle_publish.c""src/lib/handle_pubrec.c""src/lib/handle_pubrel.c""src/lib/handle_suback.c""src/lib/handle_unsuback.c""src/lib/helpers.c""src/lib/logging_mosq.c""src/lib/loop.c""src/lib/memory_mosq.c""src/lib/messages_mosq.c""src/lib/misc_mosq.c""src/lib/net_mosq.c""src/lib/net_mosq_ocsp.c""src/lib/options.c""src/lib/packet_datatypes.c""src/lib/packet_mosq.c""src/lib/property_mosq.c""src/lib/read_handle.c""src/lib/send_connect.c""src/lib/send_disconnect.c""src/lib/send_mosq.c""src/lib/send_publish.c""src/lib/send_subscribe.c""src/lib/send_unsubscribe.c""src/lib/socks_mosq.c""src/lib/srv_mosq.c""src/lib/thread_mosq.c""src/lib/time_mosq.c""src/lib/tls_mosq.c""src/lib/utf8_mosq.c""src/lib/util_mosq.c""src/lib/will_mosq.c"INCLUDE_DIRS"src/include""src"REQUIRES"mbedtls"
)
然后在ESP-IDF项目中使用:
idf.py build
6. MQTT发布订阅实战
在这一节中,将实现一个完整的MQTT发布/订阅示例,展示如何在ESP32上使用Mosquitto库。
6.1 基本概念
在MQTT中,有几个核心概念:
- 客户端:连接到MQTT代理的设备或应用程序
- 代理:负责接收消息和分发给相关订阅者
- 主题:消息的分类和路由依据,采用层级结构,如
home/livingroom/temperature
- 发布:客户端发送消息到特定主题
- 订阅:客户端注册接收特定主题的消息
- QoS:服务质量级别,决定消息传递的保证程度
6.2 设置依赖
首先,在你的ESP32项目中添加Mosquitto客户端库依赖:
// 在项目的CMakeLists.txt中添加
set(COMPONENT_REQUIRES "mosquitto")
6.3 ESP32 MQTT客户端示例
下面是一个完整的ESP32 MQTT客户端示例,能够发布和订阅消息:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"#include "lwip/err.h"
#include "lwip/sys.h"#include "mosquitto.h"/* 定义MQTT配置 */
#define MQTT_BROKER_URL "mqtt.example.com"
#define MQTT_BROKER_PORT 1883
#define MQTT_CLIENT_ID "esp32_client"
#define MQTT_USERNAME "user"
#define MQTT_PASSWORD "password"
#define MQTT_TOPIC_SUBSCRIBE "esp32/sensor/#"
#define MQTT_TOPIC_PUBLISH "esp32/status"
#define MQTT_QOS 1
#define MQTT_KEEPALIVE 60static const char *TAG = "MQTT_CLIENT";/* FreeRTOS事件组以表示连接状态 */
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;/* MQTT客户端实例 */
struct mosquitto *mosq = NULL;/* 处理WiFi事件 */
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {esp_wifi_connect();xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);}
}/* 初始化WiFi */
void wifi_init(void)
{wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));wifi_config_t wifi_config = {.sta = {.ssid = "YOUR_WIFI_SSID",.password = "YOUR_WIFI_PASSWORD",},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_start());
}/* MQTT消息回调函数 */
void mqtt_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{if(message->payloadlen) {ESP_LOGI(TAG, "Received message on topic: %s, payload: %.*s", message->topic, message->payloadlen, (char*)message->payload);// 在这里处理收到的消息// 例如:解析JSON数据、控制GPIO等} else {ESP_LOGI(TAG, "Received empty message on topic: %s", message->topic);}
}/* MQTT连接回调函数 */
void mqtt_connect_callback(struct mosquitto *mosq, void *userdata, int result)
{if(!result) {ESP_LOGI(TAG, "Connected to MQTT broker successfully");// 连接成功后订阅主题mosquitto_subscribe(mosq, NULL, MQTT_TOPIC_SUBSCRIBE, MQTT_QOS);} else {ESP_LOGE(TAG, "Failed to connect to MQTT broker: %s", mosquitto_connack_string(result));}
}/* MQTT订阅回调函数 */
void mqtt_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
{ESP_LOGI(TAG, "Subscribed to topic (mid: %d)", mid);// 发布一条连接状态消息const char *message = "{\"status\":\"online\",\"device\":\"esp32\"}";mosquitto_publish(mosq, NULL, MQTT_TOPIC_PUBLISH, strlen(message), message, MQTT_QOS, false);
}/* MQTT客户端任务 */
void mqtt_client_task(void *pvParameters)
{// 等待WiFi连接xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);ESP_LOGI(TAG, "WiFi connected, initializing MQTT client...");// 初始化mosquitto库mosquitto_lib_init();// 创建MQTT客户端实例mosq = mosquitto_new(MQTT_CLIENT_ID, true, NULL);if(!mosq) {ESP_LOGE(TAG, "Failed to create mosquitto client");vTaskDelete(NULL);return;}// 设置回调函数mosquitto_connect_callback_set(mosq, mqtt_connect_callback);mosquitto_message_callback_set(mosq, mqtt_message_callback);mosquitto_subscribe_callback_set(mosq, mqtt_subscribe_callback);// 设置认证信息(如果需要)mosquitto_username_pw_set(mosq, MQTT_USERNAME, MQTT_PASSWORD);// 连接到MQTT代理int ret = mosquitto_connect(mosq, MQTT_BROKER_URL, MQTT_BROKER_PORT, MQTT_KEEPALIVE);if(ret != MOSQ_ERR_SUCCESS) {ESP_LOGE(TAG, "Failed to connect to MQTT broker: %s", mosquitto_strerror(ret));mosquitto_destroy(mosq);vTaskDelete(NULL);return;}// MQTT客户端主循环while(1) {// 处理MQTT网络事件ret = mosquitto_loop(mosq, -1, 1);if(ret != MOSQ_ERR_SUCCESS) {ESP_LOGE(TAG, "mosquitto_loop failed: %s", mosquitto_strerror(ret));// 尝试重新连接vTaskDelay(1000 / portTICK_PERIOD_MS);if(mosquitto_reconnect(mosq) != MOSQ_ERR_SUCCESS) {ESP_LOGE(TAG, "Failed to reconnect to MQTT broker");vTaskDelay(5000 / portTICK_PERIOD_MS);}}}// 不会到达这里,但为了完整性mosquitto_destroy(mosq);mosquitto_lib_cleanup();vTaskDelete(NULL);
}/* 发布传感器数据的函数 */
void publish_sensor_data(float temperature, float humidity)
{if(mosq) {char payload[100];snprintf(payload, sizeof(payload), "{\"temperature\":%.1f,\"humidity\":%.1f}", temperature, humidity);int ret = mosquitto_publish(mosq, NULL, "esp32/sensor/data", strlen(payload), payload, MQTT_QOS, false);if(ret != MOSQ_ERR_SUCCESS) {ESP_LOGE(TAG, "Failed to publish message: %s", mosquitto_strerror(ret));} else {ESP_LOGI(TAG, "Published sensor data: %s", payload);}}
}/* 应用程序入口点 */
void app_main(void)
{// 初始化NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);// 初始化WiFiwifi_init();// 创建MQTT客户端任务xTaskCreate(mqtt_client_task, "mqtt_client_task", 4096, NULL, 5, NULL);// 模拟传感器读数并发布(实际应用中应该读取真实传感器)while(1) {// 模拟温湿度数据float temperature = 23.5f + (float)rand() / RAND_MAX * 2.0f;float humidity = 55.0f + (float)rand() / RAND_MAX * 10.0f;// 发布数据publish_sensor_data(temperature, humidity);// 每10秒发布一次vTaskDelay(10000 / portTICK_PERIOD_MS);}
}
6.4 运行效果
程序成功运行后,ESP32将:
- 连接到WiFi网络
- 连接到MQTT代理服务器
- 订阅
esp32/sensor/#
主题 - 每10秒发布温湿度数据到
esp32/sensor/data
主题 - 响应接收到的MQTT消息
7. 进阶应用与最佳实践
7.1 使用TLS/SSL加密通信
安全是物联网应用中的重要考虑因素,Mosquitto支持使用TLS/SSL加密通信:
// 设置TLS选项
mosquitto_tls_set(mosq, "ca.crt", NULL, NULL, NULL, NULL);// 如果需要验证服务器主机名
mosquitto_tls_opts_set(mosq, 1, "tlsv1.2", NULL);// 连接到加密端口(通常是8883)
mosquitto_connect(mosq, MQTT_BROKER_URL, 8883, MQTT_KEEPALIVE);
7.2 MQTT主题设计最佳实践
良好的主题设计对于物联网系统至关重要:
- 使用层级结构:例如
location/device/measurement
- 避免使用空格,使用下划线或连字符
- 保持简短但有意义
- 考虑使用主题通配符(
+
和#
)
示例主题结构:
home/livingroom/temperature
home/livingroom/humidity
home/bedroom/temperature
home/bedroom/humidity
7.3 QoS级别选择
MQTT提供三种QoS级别,应根据应用需求选择:
- QoS 0(最多一次):适用于数据可丢失的场景,如定期传感器读数
- QoS 1(至少一次):确保消息送达,但可能重复,适用于大多数物联网应用
- QoS 2(恰好一次):最高可靠性,但性能开销最大,适用于支付等关键场景
7.4 离线消息与持久会话
Mosquitto支持离线消息和持久会话功能:
// 设置clean_session为false启用持久会话
mosquitto_connect_opts_set(mosq, NULL, MQTT_KEEPALIVE, false);// 设置遗愿消息(Last Will and Testament)
mosquitto_will_set(mosq, "esp32/status", strlen("offline"), "offline", 1, true); // QoS 1, retained
7.5 优化Mosquitto性能
在资源受限环境中优化Mosquitto性能:
- 减小保持活动间隔时间(keepalive)
- 适当选择QoS级别
- 限制主题长度和负载大小
- 使用二进制协议(如CBOR或Protocol Buffers)减小负载大小
- 实现断线重连逻辑
8. 总结
在本文中,详细介绍了Mosquitto MQTT库,并比较了各种开源MQTT实现的特点。我们看到Mosquitto因其轻量级、低资源占用、成熟稳定和跨平台特性,成为嵌入式系统理想的MQTT库选择。
参考资料
- Eclipse Mosquitto官方网站
- MQTT官方规范
- ESP-IDF编程指南
相关文章:
Mosquitto MQTT库实战指南
目录 1. MQTT协议简介2. Mosquitto概述3. 开源MQTT实现对比4. 为什么选择Mosquitto5. Mosquitto的交叉编译6. MQTT发布订阅实战7. 进阶应用与最佳实践8. 总结 1. MQTT协议简介 MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻…...
C语音学习---函数指针
目录 1. 函数指针解析 2. 自定义实现(函数指针赋值) 利用下面一段例子来解析: int (*set_slave)(modbus_t *ctx, int slave); 1. 函数指针解析 set_slave 是一个 函数指针,指向一个函数。 该函数接受两个参数: mo…...
04.three官方示例+编辑器+AI快速学习webgl_animation_skinning_additive_blending
本实例主要讲解内容 这个示例展示了Three.js中**骨骼动画的叠加混合(Additive Animation Blending)**技术。通过加载一个机器人模型,演示了如何在基础动画(如站立、行走、跑步)之上叠加额外的动画效果(如潜行姿态、悲伤表情、点头同意等),实现更丰富的角…...
WSL配置docker启动nacos容器load derby-schema.sql error.问题解决方案
nacos配置问题 问题再现查看错误logsQWEN的解答不挂载/data结论 问题再现 本来想要本地跑一下nacos,之前都是直接在Linux环境下面,现在就使用windows的wsl跑一下nacos,之前是需要先配置/conf文件下面的porperties文件以及构建对应的nacos-config数据库。所以我使用…...
游戏引擎学习第272天:显式移动转换
回顾并为今天的内容铺垫背景 我们刚开始为游戏主角编写一些程序逻辑,因为我们之前已经完成了大部分引擎方面的开发,现在可以专注在角色身上。这个角色的移动方式会有些特别,与大多数游戏角色的运动机制不太一样。我们当前正在实现的控制方式…...
AVL树解析
插入操作 // 插入操作 bool insert(const pair<K, V>& kv) {// 若树为空,直接构造,new一个if (_root nullptr) {_root new Node(kv);return true;}// 用于遍历树的当前节点Node* cur _root;// 用于记录当前节点的父节点Node* parent n…...
vue 中的数据代理
在 Vue 中,数据代理(Data Proxy) 是 Vue 实现 MVVM 模式 的关键技术之一。Vue 使用数据代理让你可以通过 this.message 访问 data.message,而不需要写 this.data.message —— 这大大简化了模板和逻辑代码。 我们来深入理解它的本…...
Linux共享内存深度解析:从内核机制到云原生应用
引言:超越进程边界的内存魔术 在Linux系统的进程间通信(IPC)领域,共享内存(Shared Memory)如同魔法镜子般的存在——不同进程透过它看到相同的内存镜像。这种机制摒弃了数据拷贝,直击性能瓶颈&…...
Vue Router全局拦截
Vue Router全局拦截全攻略 一、为什么需要全局拦截? 最近在开发后台管理系统时,突然发现所有页面都需要登录才能访问。如果每个页面都手动检查登录状态,那代码简直要写成意大利面条了。这时候,Vue Router的全局拦截功能就像个贴…...
从0开始学linux韦东山教程第三章问题小结(3)
本人从0开始学习linux,使用的是韦东山的教程,在跟着课程学习的情况下的所遇到的问题的总结,理论虽枯燥但是是基础。说实在的越看视频越感觉他讲的有点乱后续将以他的新版PDF手册为中心,视频作为辅助理解的工具。参考手册为嵌入式Linux应用开发…...
【前端】【css】【总复习】三万字详解CSS 知识体系
🌈 CSS 知识体系目录大纲 一、基础知识入门 1. CSS 简介与作用 CSS(Cascading Style Sheets,层叠样式表)是一种用于给 HTML 页面添加样式的语言,作用是让网页更美观、结构更清晰、布局更灵活。 核心作用: 控制网页元素的 颜色、字体、间距、边框、背景布局网页元素位置…...
Linux 进程等待
1、进程等待 僵尸进程 是一个比较麻烦的问题,如果不对其做出处理,僵尸进程 就会越来越多,导致 内存泄漏 和 标识符 占用问题 进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为…...
轻量服务器与宝塔
因为访问宝塔面板是需要在安全组设置一下开放端口,比如这里是42450 但是我们用的轻量服务器是把安全组这种功能削减了的,所以我就去尝试修改了一下防火墙设置 然后就可以访问了...
深入理解AMBA总线(六)AHB-lite Slave响应和其它控制信号
上一篇文章给大家介绍了AHB-lite的一些控制信号,重点是通过这些控制信号去理解AHB-lite为什么这么设计,采用这些控制信号有什么好处。这节课给大家带来剩余的一些控制信号介绍。 ** 1、Slave Response Signaling ** 1.1、Slave Transfer Responses …...
app加固
1、什么是加固? 我们之前讲的逆向,大多数都是用加密算法去加密一些明文字符串,然后把得到的结果用 Base64、Hex等进行编码后提交。加固其实也一样,只不过他通常加密的是 dex文件而已。但是 dex 文件加密以后,安卓系统是没法直接运行的。所以加固的核心&…...
Linux架构篇、第三章_2_Linux服务器监控与NGINX优化
Linux_架构篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目: 版本号: 1.0,0 作者: 老王要学习 日期: 2025.05.11 适用环境: Centos7 文档说明 本文围绕 Linux 服务器监控与 NGINX 优化展开。介绍了 sysst…...
第26节:卷积神经网络(CNN)-数据增强技术(PyTorch)
1. 引言 在深度学习领域,数据增强(Data Augmentation)是提升卷积神经网络(CNN)性能的关键技术之一。通过人为地扩展训练数据集,数据增强能够有效提高模型的泛化能力,防止过拟合,特别是在训练数据有限的情况下。本文将全面介绍PyTorch框架下的数据增强技术,包括基本原理、…...
架构思维:通用架构模式_怀疑下游的设计思路与最佳实践
文章目录 1. 引言2. 为什么要“怀疑下游”3. 三大类下游依赖及应对方案3.1 对其他微服务的依赖3.1.1 分布式事务简易补偿方案3.2 对数据库的依赖3.3 对消息中间件的依赖 4. 分布式事务实战案例5. 小结 1. 引言 在 架构思维:通用架构模式_从设计到代码构建稳如磐石的…...
[Java实战]Spring Boot 中Starter机制与自定义Starter实战(九)
[Java实战]Spring Boot 中Starter机制与自定义Starter实战(九) 引言 Spring Boot 的 Starter 是其“约定优于配置”理念的核心体现,通过简化依赖管理和自动配置,极大提升了开发效率。本文将深入剖析 Starter 的设计思想、实现原…...
C++23 views::repeat (P2474R2) 深入解析
文章目录 引言C20 Ranges库回顾什么是Rangesstd::views的作用 views::repeat概述基本概念原型定义工作原理应用场景初始化容器模拟测试数据 总结 引言 在C的发展历程中,每一个新版本都会带来一系列令人期待的新特性,这些特性不仅提升了语言的性能和表达…...
【第三十五周】Janus-pro 技术报告阅读笔记
Janus-Pro 摘要Abstract文章信息引言方法Janus 架构Janus 训练Janus-Pro 的改进 实验结果总结 摘要 本篇博客介绍了Janus-Pro,这是一个突破性的多模态理解与生成统一模型,其核心思想是通过解耦双路径视觉编码架构解决传统方法中语义理解与像素生成的任务…...
基于Qt的app开发第七天
写在前面 笔者是大一下计科生,标题这个项目是笔者这个学期的课设,与学长共创,我负责客户端部分,现在已经实现了待办板块的新建、修改。 这个项目目前已经走上正轨了,博主也实现了主要功能的从无到有ÿ…...
第二十二节:图像金字塔-拉普拉斯金字塔
在数字图像处理的奇幻世界中,存在着一种能够连接不同视觉维度的神秘阶梯——图像金字塔。这种独特的结构让计算机视觉算法能够在不同尺度下观察和理解图像特征,而其中的拉普拉斯金字塔更是隐藏着图像细节重构的终极奥秘。 一、金字塔的数学基础:从高斯到拉普拉斯 1.1 高斯金…...
Flutter基础()
导航栏 appBar: AppBar() title: const Text(搜索) //标题 backgroundColor: Colors.blue //背景颜色 centerTitle: true //标题居中leading 属性 作用: 放置在应用栏左侧的控件,通常是一个图标按钮,用于导航或打开菜单。 AppBar(le…...
ES面试题系列「一」
1、Elasticsearch 是什么?它与传统数据库有什么区别? 答案:Elasticsearch 是一个基于 Lucene 的分布式、开源的搜索和分析引擎,主要用于处理大量的文本数据,提供快速的搜索和分析功能。与传统数据库相比,E…...
Oracle 通过 ROWID 批量更新表
Oracle 通过 ROWID 批量更新表 在 Oracle 数据库中,使用 ROWID 进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销。 ROWID 基本概念 ROWID 是 Oracle 数据库中每一行的唯一物理地址标识符ÿ…...
罗技无线鼠标的配对方法
罗技鼠标的配对方法: 重新连接鼠标 请按照以下步骤将鼠标与 USB 接收器重新配对。 1.将USB接收器插入计算机。 2.将鼠标关闭电源。 3.按住并持续按住向右按钮,直到操作结束。 4.切换鼠标电源。 5. 单击一次左侧按钮。 6. 单击一次中间按钮。 7.全部松开&…...
移动应用开发的六大设计原则
在移动应用开发中,遵循设计原则能大幅提升代码的可维护性和扩展性。本文以一个简单的学生管理系统为例,解析六大核心设计原则的实践方法。 1. 单一职责原则 优点: 提高可维护性:一个类只负责一项职责,代码的功能会更…...
LLM初识
从零到一:用 Python 和 LLM 构建你的专属本地知识库问答机器人 摘要: 随着大型语言模型(LLM)的兴起,构建智能问答系统变得前所未有的简单。本文将详细介绍如何使用 Python,结合开源的 LLM 和向量数据库技…...
【CTF】Linux Shell RCE绕过(bypass)技术总结
在Linux环境下,远程代码执行(RCE,Remote Code Execution)是一种常见的攻击手段。然而,许多系统会对命令注入进行过滤或限制,例如禁止特定关键字(如system)、斜杠(/&#…...
深入理解 Linux 权限控制机制
引言 在 Linux 系统中,权限控制是保障系统安全的核心机制。通过限制用户对文件和资源的访问,它能有效防止未授权操作,保护数据不被篡改或泄露。合理设置权限不仅有助于实现用户隔离和最小权限原则,还能降低系统被滥用或攻击的风险…...
技术书籍推荐(002)
20. 利用Python进行数据分析 免费 电子书 PDF 下载 书籍简介: 本书聚焦于使用Python进行数据处理和分析。详细介绍了Python中用于数据分析的重要库,如NumPy(提供高效的数值计算功能,包括数组操作、数学函数等)、panda…...
[SAP] SAP ERP用户参数设置
菜单路径 个人默认值的设置(数值,日期,时间) 个人参数值的设置 在给参数设置参数值后,当用户登录到对应功能页面时,这些参数值就会自动带出来 例如,我们分别对上述AAT,VKO以及VTW这3个参数设置了参数值&am…...
Python中,async和with结合使用,有什么好处?
在Python的异步编程中,async和with的结合使用(即async with)为开发者提供了一种优雅且高效的资源管理模式。这种组合不仅简化了异步代码的编写,还显著提升了程序的健壮性和可维护性。以下是其核心优势及典型应用场景的分析&#x…...
【信息系统项目管理师】第3章:信息系统治理 - 29个经典题目及详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第…...
python实战项目69:基于Python爬虫的链家二手房数据采集方法研究
python实战项目69:链家二手房数据采集 一、项目需求1.1 房地产数据价值1.2 传统数据获取局限性1.3 技术可行性二、数据采集流程2.1 需求分析2.2 网页结构分析2.3 请求发送与反爬策略2.4 数据解析2.5 数据存储三、结论与展望四、完整代码一、项目需求 本文针对房地产数据分析需…...
PowerShell 脚本中文乱码处理
问题描述 脚本带中文,执行时命令行窗口会显示出乱码 示例 Write-Host "测试成功!"解决方法 问了DeepSeek,让确认是不是 UTF8 无 BOM 格式 事实证明方向对了 但是确认信息有偏差 改成 UTF8 with BOM 使用任意支持修改编码的文本…...
SpEL(Spring Expression Language)使用详解
SpEL(Spring Expression Language)是 Spring 框架中一种强大的表达式语言,支持在运行时动态查询和操作对象图。它与 Spring 生态深度集成,广泛应用于依赖注入、数据绑定、AOP、安全规则等场景。以下是其核心语法、应用场景及使用示…...
论文阅读与写作:《从探索到突破:解密科研和论文写作的思维密码》
文章目录 一、如何做科研1.科研的步骤2.课题选择3.快速入门一个新领域:读论文,先读综述(1)自己看论文的时候,每篇论文花3-5分钟记录一下自己的idea和一些瞬间的想法(2)高质量文献:顶会顶刊(3)如何检索 4.注重团队协作与学术交流5.…...
免费公共DNS服务器推荐
当自动获取的DNS或本地运营商的DNS出现问题,可能导致软件无法连接服务器。此时,手动修改电脑的DNS设置或许能解决问题。许多用户觉得电脑上网速度慢、游戏卡顿,归咎于DNS问题。确实,我们可以自行设置一个DNS来改善网络体验。不少用…...
CK-S650-PA60S半导体专用读写器|读写头与绿联RS232串口转接头联机测试说明
CK-S650-PA60S半导体专用读写器|读写头是一款国产替代欧姆龙V640系列,支持德州仪器公司(TI)制造的RI-TRP-DR2B、RI-TRP-WR2B-40低频玻璃管标签|射频标签读写,广泛应用半导体硅片盒、晶圆盒、花篮等RFID插件识别与产品追溯领域。 CK-S650-PA60S半导体专用…...
Babel 基础使用指南:从安装到编译的完整流程
Babel 是当今前端开发中不可或缺的工具,它允许开发者使用最新的 JavaScript 特性,同时确保代码能在各种浏览器和环境中运行。本文将带你从零开始学习 Babel 的基础使用,涵盖安装、配置到实际编译的全过程。 1. 安装 Babel 和插件 首先&…...
uniapp-商城-52-后台 商家信息(商家信息数据,云对象使用)
1、概述 已经通过好几个篇幅来说明商家信息,包括logo、商家名称,地址,电话以及商家简介。通过表单组件和标签,以及我们的文件上传标签,都做了说明。(logo上传,用的文件上传组件是上传到公共的数…...
【我的创作纪念日】512
机缘 还记得 2023 年 12 月 15 日,我撰写了第 1 篇技术博客:《oracle 跟踪文件--审计日志》。从此,这平凡的一天,赋予了我不平凡的意义。在那一刻,我已在创作这趟旅程中出发,并立志将工作中的经验总结&…...
共享内存与信号量结合
在Linux系统中,进程间通信(IPC)和原子性是并发编程中的核心问题。以下是对这些概念的详细分步解释: 一、进程间通信(IPC)方法 1. 管道(Pipe) 匿名管道:用于父子进程等有…...
西门子PLC s7-1200工艺对象“轴”的应用(1)
1. 工艺对象 “ 轴 ” 的概念 在西门子 S7-1200 PLC 中,术语 “ 轴 ” 特指用 “ 轴 ” 工艺对象表示的驱动器工艺映像。 “ 轴 ” 工艺对象是用 户程序与驱动器之间的接口,用于接收用户程序中的运动控制命令、执行这些命令并监视其运行情况。 运动控制…...
ubuntu22.04在 Docker容器中安装 ROS2-Humble
22.04 安装 docker 容器并实现rviz功能 1 docker pull命令拉取包含ROS-Humble的镜像: docker pull osrf/ros:humble-desktop-full-jammy docker images验证该镜像是否拉取成功。 使用镜像osrf/ros:humble-desktop-full-jammy创建并运行容器 sudo docker run -it…...
【LwIP源码学习6】UDP部分源码分析
前言 本文对lwip协议栈里UDP部分的源码进行分析。将源码中最关键部分提取出来,梳理UDP部分的设计框架。 应用层例子 首先举一个应用层使用UDP的简单例子,如下: //第一步:申请套接字 sock socket(AF_INET, SOCK_DGRAM, 0); //…...
Python Cookbook-7.10 在 MySQL 数据库中储存 BLOB
任务 想把一个二进制的大对象(BLOB)存入MySQL数据库 解决方案 MySQLdb 模块并不支持完整的占位符,不过可以使用模块的escape_string 函数来解决: import MySQLdb,cPickle #连接到数据库,用你的本机来测试数据库,并获得游标 connection = MySQLdb.connect(db = "tes…...
LWIP的ICMP协议
ICMP协议简介 ICMP协议是一个网络层协议 背景:如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。因此我们需要ICMP协议来完成这样的功能 为什么需要ICMP协议 1,IP 协议本身不提供差错报告和差错控制机制来保证数据报递交的有效…...