从零玩转MQTT协议:Mosquitto的C语言客户端编程避坑指南

MQTT通信协议(mosquitto)发布订阅例子C语言实现 MQTT通信协议mosquitto发布订阅例子C语言实现一、前言二、同步函数具体代码运行结果三、异步函数具体代码运行结果四、可订阅可发布模式具体代码运行结果附录 一、前言 前面对MQTT进行了简单的介绍,并了解了如何在Linux上搭建MQTT 的运行 环境,参考链接:MQTT通信协议(mosquitto)在Linux上的环境构建与测试,那些仅仅是通过命令去测试,现在我们来通过mosquitto的官方源码,编程实现MQTT协议的发布订阅。 上一章中通过源码编译安装后,将会有几个我们需要用到的文件。对应路径如下 阅读详情

从零玩转MQTT协议:Mosquitto的C语言客户端编程避坑指南

在物联网设备开发中,MQTT协议因其轻量级、低功耗和高效的消息传递机制成为首选通信方案。作为最流行的开源MQTT broker之一,Mosquitto不仅提供了稳定的消息代理服务,其配套的libmosquitto库更为嵌入式开发者提供了强大的客户端编程能力。本文将深入探讨如何避开C语言客户端开发中的常见陷阱,构建高可靠的物联网通信模块。

1. libmosquitto库的核心架构解析

libmosquitto采用事件驱动模型设计,其核心结构体mosquitto封装了所有客户端状态和网络交互细节。理解这一架构是避免内存泄漏和资源竞争的关键。

struct mosquitto {
    // 网络连接相关
    int sock;
    SSL *ssl;
    
    // 消息队列管理
    struct mosquitto_message_all *msgs;
    struct mosquitto_message_all *last_msg;
    
    // 回调函数指针
    void (*on_connect)(struct mosquitto *, void *, int);
    void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *);
    
    // 线程安全控制
    pthread_mutex_t callback_mutex;
    pthread_mutex_t state_mutex;
};

内存管理三原则:

  1. 每个mosquitto_new()必须对应mosquitto_destroy()
  2. mosquitto_lib_init()与mosquitto_lib_cleanup()成对出现
  3. 消息payload内存由库自动分配释放,无需手动管理

注意:在嵌入式环境中,建议在程序启动时调用一次mosquitto_lib_init(),而不是为每个客户端实例初始化,避免重复加载加密库消耗资源。

2. 连接稳定性增强实践

工业现场网络环境复杂,需要实现自动重连和异常恢复机制。以下是通过状态机实现的增强连接方案:

enum conn_state {
    DISCONNECTED,
    CONNECTING,
    CONNECTED,
    RECONNECTING
};

void connection_control(struct mosquitto *mosq) {
    static enum conn_state state = DISCONNECTED;
    static int retry_count = 0;
    
    switch(state) {
        case DISCONNECTED:
            if(mosquitto_connect_async(mosq, host, port, keepalive) == MOSQ_ERR_SUCCESS) {
                state = CONNECTING;
                retry_count = 0;
            }
            break;
            
        case CONNECTING:
            // 超时处理
            if(++retry_count > MAX_RETRY) {
                state = DISCONNECTED;
                sleep(BACKOFF_TIME);
            }
            break;
            
        case CONNECTED:
            // 心跳检测
            if(last_ping_time + keepalive < time(NULL)) {
                state = RECONNECTING;
            }
            break;
            
        case RECONNECTING:
            mosquitto_reconnect_async(mosq);
            state = CONNECTING;
            break;
    }
}

关键参数调优:

参数默认值工业场景建议值说明
keepalive60s300s降低心跳频率节省能耗
max_inflight205限制未确认消息数量
reconnect_delay1s5s避免频繁重连消耗资源

3. QoS级别与消息可靠性保障

MQTT提供三种服务质量等级,不同级别直接影响消息传输的可靠性和系统资源消耗:

QoS实现对比:

// QoS 0 - 最多一次
mosquitto_publish(mosq, NULL, "topic", strlen(msg), msg, 0, false);

// QoS 1 - 至少一次
mosquitto_publish(mosq, &mid, "topic", strlen(msg), msg, 1, false);

// QoS 2 - 恰好一次 
mosquitto_publish(mosq, &mid, "topic", strlen(msg), msg, 2, false);

QoS选择策略:

  1. 传感器数据采集:QoS 0 + 时间戳,适用于高频低价值数据
  2. 设备控制指令:QoS 2,确保关键操作准确执行
  3. 固件升级包:QoS 1 + 分片传输,平衡可靠性和效率

实测数据:在STM32F407+ESP8266平台上,QoS 2的消息延迟比QoS 0高3-5倍,内存占用多40%。建议仅在必要时使用QoS 2。

4. 跨平台移植与ARM交叉编译

针对嵌入式Linux设备的交叉编译需要特别注意库依赖关系。以下是完整的交叉编译示例:

# 下载源码
wget https://mosquitto.org/files/source/mosquitto-2.0.14.tar.gz
tar -zxvf mosquitto-2.0.14.tar.gz

# 配置编译选项
cd mosquitto-2.0.14
CC=arm-linux-gnueabihf-gcc \
CXX=arm-linux-gnueabihf-g++ \
make WITH_SRV=no WITH_WEBSOCKETS=no WITH_TLS=yes \
     WITH_CJSON=no WITH_THREADING=yes \
     LIB_SUFFIX=arm
     
# 安装到目标目录
make install DESTDIR=/opt/mosquitto-arm

常见移植问题解决:

  1. 符号未定义错误:检查openssl库路径是否包含在LD_LIBRARY_PATH中
  2. 段错误:确认CPU架构匹配(armv7 vs armv8)
  3. TLS连接失败:检查交叉编译的openssl是否支持ARM硬件加密指令

5. 高级特性实战:遗嘱消息与保留消息

遗嘱消息(LWT)能在设备异常离线时通知其他客户端,是物联网系统的关键保障机制:

// 设置遗嘱消息
mosquitto_will_set(mosq, "device/status", 7, "offline", 1, true);

// 清除遗嘱(正常断开时调用)
mosquitto_will_clear(mosq);

保留消息的使用场景对比:

场景使用建议示例
设备最新状态适合使用保留消息mosquitto_publish(..., true)
历史数据记录不应使用保留消息存储到数据库
频繁更新的传感器配合retain_available参数每10分钟更新一次保留消息

6. 性能优化与内存管理

嵌入式设备资源有限,需要通过以下手段优化性能:

内存池技术:

#define MSG_POOL_SIZE 10
static struct mosquitto_message msg_pool[MSG_POOL_SIZE];

struct mosquitto_message* alloc_msg() {
    for(int i=0; i<MSG_POOL_SIZE; i++) {
        if(msg_pool[i].payload == NULL) {
            return &msg_pool[i];
        }
    }
    return NULL;
}

void free_msg(struct mosquitto_message *msg) {
    memset(msg, 0, sizeof(struct mosquitto_message));
}

网络参数调优:

# mosquitto.conf 关键参数
max_inflight_messages 20     # 限制飞行中消息数量
max_queued_messages 1000     # 防止内存耗尽
persistent_client_expiration 1h # 清理不活跃客户端

7. 安全加固方案

物联网设备面临严峻的安全挑战,必须实现端到端的安全防护:

TLS双向认证配置:

// 客户端配置
mosquitto_tls_set(mosq, "/path/to/ca.crt", 
                 NULL, "/path/to/client.crt",
                 "/path/to/client.key", NULL);

// 服务端配置(mosquitto.conf)
listener 8883
cafile /etc/mosquitto/ca.crt
certfile /etc/mosquitto/server.crt
keyfile /etc/mosquitto/server.key
require_certificate true

认证方案对比:

方案安全性资源消耗适用场景
用户名/密码低低内部测试环境
TLS单向认证中中一般生产环境
TLS双向认证高高金融、医疗等关键领域

在实际项目中,我们曾遇到因未设置tls_version导致的安全漏洞。建议明确指定TLS版本:

mosquitto_int_option(mosq, MOSQ_OPT_TLS_VERSION, MOSQ_SSL_TLSv1_2);

8. 调试技巧与问题排查

高效的调试能大幅缩短开发周期,以下是验证过的调试方法:

网络状态监控:

# 查看MQTT连接状态
watch -n 1 "netstat -antp | grep 1883"

# 实时监控主题消息
mosquitto_sub -v -t '$SYS/broker/bytes/#' -u admin -P password

常见错误代码处理:

错误代码原因分析解决方案
MOSQ_ERR_CONN_REFUSED认证失败或端口错误检查用户名密码和防火墙设置
MOSQ_ERR_NO_CONN网络连接已断开实现自动重连机制
MOSQ_ERR_PROTOCOL协议版本不匹配确认客户端和服务端版本兼容性
MOSQ_ERR_CONN_LOST心跳超时调整keepalive参数

在开发基于STM32的智能电表项目时,我们通过Wireshark抓包发现QoS 1消息重复问题,最终发现是未正确处理PUBACK导致的。这提醒我们:所有MQTT错误代码都必须处理,不能简单忽略。

MQTT----基于mosquitto库C语言实现发布和订阅 一.MQTT是什么 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议 阅读详情

相关推荐

Mosquitto 客户端使用介绍

简介 ​ Mosquitto是用C语言实现了MQTT(Message Queueing Telemetry Transport)协议的Broker,EMQ君在本文对MQTT协议不做过多的赘述,关于 MQTT 协议的介绍读者可以阅读EMQ的MQTT协议介绍。 本文重点介绍mosquito客户端的使用。 安装 Mosquitto安装,可以参考EMQ君之前写的Ubuntu上搭建Mosquitto ...

无语僧 5808

状态机模型详细介绍:概念、原理、使用方法及源码解析

状态机模型详细介绍:概念、原理、使用方法及源码解析

深耕嵌入式领用多年, 致力于分享嵌入式领域技术! 3327

【MQTT协议】使用c++实现mqtt协议(Mosquitto源码编译)

MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模式的消息传输协议,其最初由IBM开发,现已成为OASIS标准。MQTT协议常用于物联网领域,特别是在传输低带宽、高延迟、不稳定网络条件下的数据,例如传感器数据和遥测数据等。MQTT协议的优点:轻量级:MQTT协议的设计十分轻量级,其开销比较小,传输的数据包大小也比较小,这使得MQTT协议非常适合在低带宽、高延迟的网络环境下使用。

种一棵树最好的时间是十年前,其次是现在 8795

基于MQTT协议的Mosquitto的使用及libmosquitto客户端编程

1,MQTT简介  MQTT 是一个轻量级协议,使用基于 TCP/IP 协议的发布/订阅消息转发模式,在物联网应用中大规模使用。 MQTT 协议的中心是 broker( 服务器/代理) ,客户端通过订阅消息和发布消息进行数据交互 ,如下图所示:  2,Mosquitto安装  (1)mosquitto下载  下载地址,进入下载页面,选择source中第一个下载mosquitto-1.4.9.t...

danwuxie的博客 6968

MQTT协议之本地MQTT服务器环境搭建与测试(Mosquitto)

本篇为MQTT协议系列的第二篇,主题为本地MQTT服务器环境搭建与测试,查完完整目录点击此处 0x01 开发机环境 本文中开发机为虚拟机,虚拟机系统为Ubuntu Server 18.04。 客户端使用MQTT.fx,版本为1.7.1,最新版收费,用不了,简单测试的话,1.7.1已经足够了。 0x02 安装配置Mosquitto环境 Mosquitto是一个轻量级的开源消息代理,实现了MQTT协议,用来了解MQTT协议,当做Broker比较合适(只在开始了解的时候用了一下,感觉管理不是很方便,后面使用的都是

qq_34485436的博客 3668

MQTT协议之Mosquitto

MQTT协议及其开源实现Mosquitto简介及其使用测试。

weixin_45430676的博客 1510

MQTT简介和mosquitto安装与使用及利用mosquitto库Linux c编程

一、MQTT简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议;Mosquitto是一个实现了MQTT3.1协议的代理服务器,由MQTT协议创始人之一的Andy Stanford-Clark开发,应用广泛的低功耗传感器,手...

WuYujun's blog 2万+

MQTT实战:5分钟用Mosquitto搭建本地物联网消息服务器(附C语言客户端Demo)

本文提供了在Ubuntu系统上快速搭建Mosquitto MQTT消息代理服务器的实战教程,并附有完整的C语言客户端编程示例。通过详细的步骤和代码演示,帮助开发者快速掌握MQTT协议的核心概念,包括发布/订阅模式、主题通配符、QoS级别以及如何使用libmosquitto库进行客户端开发,从而构建本地物联网消息系统。

ol789012345的博客 852

mqtt客户端演示(MQTT通信协议(mosquitto)发布订阅例子C语言实现)

MQTT客户端 struct mosquitto *mosq; void my_connect_callback(struct mosquitto *mosq, void *obj, int rc) { //printf("rc11: %d\n", rc); } void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result) { mosquitto_destroy(mo...

$好记性还是要多记录$ 3645

mqtt之mosquitto使用

mosquitto是一个开源broker,并且支持MQTTv3.1,支持客户端的验证。mosquitto包括服务端和客户端。 1、mosquitto_sub command:订阅主题,接收到消息时打印 mosquitto_sub [-c] [-d] [-h hostname] [-i client_id] [-I client id prefix] [-k keepalive time] [-p port number] [-q message QoS] [--quiet] [-v] [ -u usern

michael_linux的博客,一个小小小学生。滴水穿石,步步为营,只为那刹那芳华。 1438

实现 PDF 添加水印的五种方式

PDF(Portable Document Format,便携式文档格式)是一种流行的文件格式,它可以在多个操作系统和应用程序中进行查看和打印。在某些情况下,我们需要对 PDF 文件添加水印,以使其更具有辨识度或者保护其版权。本文将介绍如何使用 Spring Boot 来实现 PDF 添加水印的方式。

逸轩 6474

Mosquitto MQTT库实战指南

Eclipse Mosquitto是一个实现了MQTT协议3.1和3.1.1版本的开源消息代理软件。它由Eclipse Foundation维护,使用C语言编写,具有轻量级、低资源消耗和高性能的特点,特别适合在嵌入式设备和资源受限环境中使用

Psyduck_ing的博客 3215

从芯片原厂到BSP工程师:技术转型与核心能力解析

嵌入式系统开发中,BSP(板级支持包)作为连接硬件与操作系统的关键层,其开发能力直接影响设备稳定性与性能。理解Linux内核架构(如内存管理、进程调度)和基础接口协议(I2C/SPI/USB)是BSP工程师的核心技能。在芯片验证与驱动开发场景中,多核异构系统调试与稳定性问题排查(如死机分析)展现了工程师的实战能力。随着物联网与智能设备发展,掌握从硬件适配到系统优化的全链路技术栈,成为职业发展的关键突破点。

weixin_36012152的博客 600

基于mosquitto的MQTT客户端实现C语言

在对MQTT的学习过程中 一下的内容对我提供了帮助https://www.runoob.com/w3cnote/mqtt-intro.html 对MQTT的入门级介绍 很基础讲解了什么是MQTThttps://mosquitto.org/api/files/mosquitto-h.html 这个网站记载了几乎所有的mosquitto的接口 你想知道的函数接口他都有 函数简介可能看不出来什么 点进去看一下详细解释还是很清晰的 以下的图片能够更加直观地说明MQTT协议的通信方式 根据这两张图片谈...

whyrookie的博客 1356

基于PDF文档结构的数字隐写

PDF隐写

xiongshivigor的博客 1426

Cisco Packet Tracer 7.3免登录技巧:3种方法快速跳过注册界面(附详细截图)

本文针对Cisco Packet Tracer 7.3启动时遇到的登录界面问题,提供了三种合法高效的解决方案。详细介绍了如何利用官方访客模式快速启动、注册思科账号实现一劳永逸登录,以及通过调整本地安装配置优化启动流程,帮助网络学习者与备考者绕过繁琐步骤,快速进入实验环境。

weixin_29305337的博客 744

mosquitto c语言编程,MQTT通讯协议(mosquitto)发布订阅例子C语言实现

1、前言前面对MQTT进行了简单的介绍,并了解了如何在Linux上搭建MQTT 的运行 环境,参考连接:MQTT通讯协议(mosquitto)在Linux上的环境构建与测试,那些仅仅是经过命令去测试,如今咱们来经过mosquitto的官方源码,编程实现MQTT协议的发布订阅。上一章中经过源码编译安装后,将会有几个咱们须要用到的文件。对应路径以下:htmlmosquitto-1.6.10/lib/l...

weixin_36440941的博客 2344

2.STM32F407ZGT6 学习笔记-移植 FreeRTOS

1. 在工程下建议FreeRTOS文件夹 2. 在FreeRTOS文件夹下建立 src 和 port 文件夹 (src用于存放freertos源码,port文件夹存放内存和接口相关的文件) 3. 复制freertos/source文件夹下所有c文件复制到刚刚建立的freertos/src目录下 4. 复制FreeRTOSv9.0.0\FreeRTOS\Source\portablex下的MemMang和RVDS文件夹复制到刚刚建立的port问价夹下 5. 将FreeRTOSv9.0.0\FreeRTOS

Car12 1234

c++ mqtt客户端_简单认识认识mqtt及mosquitto

小编对Linux这一块的实际开发经验虽然还不是很足,但也知道进程间通信有那么几种方式:管道、消息队列、共享内存、套接字等。某项目中使用了MQTT作为进程间的通信方式,感觉很新颖,网上好像也比较少有看到使用MQTT来作为进程间通信的方式的。这两篇笔记我们就来一起学习一下这种方式。MQTT的一些介绍❝以下介绍内容来自《[野火]《LwIP应用开发实战指南》❞MQTT 协议全称是 Message...

weixin_39811478的博客 1797

Linux | Ubuntu18.04安装RTX 4060显卡驱动完整教程

本节详细介绍了如何在ubuntu18系统安装4060显卡的驱动。

九七的博客 5160

《YOLOv8:从入门到实战》报错解决 & 专栏答疑

《YOLOv8:从入门到实战》专栏上线后,部分同学在学习过程中提出了一些问题,笔者相信这些问题其他同学也有可能遇到。为了让大家可以更好地学习本专栏内容,笔者特意推出了该篇专栏答疑,针对同学们在学习过程中所提出的问题进行汇总记录,并不断实时更新,希望能够帮助到大家!🌈

小哥谈 1241

REA(rea-agents):用编码代理逆向任意软件——从原生二进制到 MCP 工具的完整实践指南

本篇指南基于 REA 项目(npm 包名 `rea-agents`)的韩语主 README,系统讲解如何把 REA 接入 Claude Code、Cursor、Codex 等编码代理,使其能够借助 Hopper/Ghidra 对无源码的应用进行有证据支撑的逆向分析,并把结论落地为自己的产品功能。读完本文,你将掌握 REA 的安装与 `setup` 配置全流程、CLI 与 MCP 两种使用方式的差异

gitblog_00265的博客 959

YOLOv11改进策略【Conv和Transformer】| IJCAI 2024 利用FreqFormer中的SFA 空间 - 频率注意力和CTA 通道转置注意力 二次改进C3k2

在FreqFormer模型中,SFA(Spatial-Frequency Attention)和CTA(Channel Transposed Attention)模块是关键组成部分,它们针对传统Transformer在图像超分辨率任务中的不足而设计,旨在更好地恢复高频细节,提升模型性能。

Limiiiing的博客 761

用C语言实现mosquitto MQTT订阅消息

陈拓 2021/04/15-2021/04/15 1. 概述 在《MQTT服务器Mosquitto 2.x编译安装配置》 https://zhuanlan.zhihu.com/p/365103802 https://blog.youkuaiyun.com/chentuo2000/article/details/115731687 一文中我们下载了最新的mosquitto源码进行了编译安装。 在下载的源码中有几个C语言的例子可以参考: 这些例子在github上也可以找到: https://git.

晨之清风 1981

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Eclipse Mosquitto 技术史:IBM 将 MQTT Java/C 客户端捐赠给 Eclipse 基金会与 Paho 项目的诞生

2011 年 11 月,IBM 与 Eurotech 宣布将 MQTT 协议捐赠给 Eclipse 基金会,并启动 Eclipse Paho 开源项目,由 IBM 贡献 Java 与 C 两套客户端实现。本文还原这一事件的完整脉络,并结合当前仓库中的许可证文件、ChangeLog 与官方博客,考证这次捐赠如何直接塑造了今天 MQTT 客户端生态的格局——读完你可以清楚 Paho 客户端的来历,以及

gitblog_00313的博客 782

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

解析 Eclipse Mosquitto:MQTT 协议的开源服务器与客户端实现(JOSS 论文导读)

本文以仓库内 [doc/joss-paper/paper.md](https://link.gitcode.com/i/4b16c8077ca8c478a5542328db451d4b) 这一篇发表于《Journal of Open Source Software》(JOSS)的论文为核心骨架,系统拆解 Eclipse Mosquitto 项目的三大组成部分——MQTT 服务器(broker)、`

gitblog_00738的博客 628

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: 从麦克风到云端:基于ESP32 S3的语音采集系统设计全解析(含SPIFFS存储优化)
下一篇: Anaconda下如何正确配置arcpy环境?手把手教你避开32/64位兼容性坑
python9snake
博客等级 码龄1天 0粉丝 1724原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值