MQTT版本升级过程及源码解析

  首先说一下为什么要写这篇文章呢,在我发现网上对MQTT的文章介绍实在太少了,可能也是使用这个的频率比较低吧!还有对问题的定位以及解决的方式和办法也太少了,所以特意写这篇文章希望能作出一些贡献,帮助到一些需要的人。

  主要记录一下MQTT在原先1.2.0版本使用过程中出现的问题,排查问题到升级1.2.1版本过程中出现的问题,通过源码一步步排查出最后的问题点,直到符合预期目标。

 

<!-- https://mvnrepository.com/artifact/org.eclipse.paho/org.eclipse.paho.client.mqttv3 -->
<dependency>
    <groupId>org.eclipse.paho</groupId>
    <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.1</version>
</dependency>

  MQTT的搭建及SSL认证可以参考这个博客:https://www.cnblogs.com/yueli/p/7490453.html 在这不仔细阐述


  Qos介绍 

  在开头先了解一下Qos的一些含义,也是这个问题为导火线

  • Qos = 0  最多一次的传输

       发布者PUBLISH消息到服务器(broker),发送即丢弃。没有确认消息,也不知道对方是否收到。网络层面,传输压力小

  • Qos = 1  至少一次的传输

   发布者发布消息保存消息,服务器(broker)接收到消息,服务器(broker)PUBLISH到订阅者,服务器(broker)回一个PUBACK信息到发布者让删除消息,然后订阅者接收消息后PUBACK给服务器让删除消息。如果失败了,在一段时间确认信息没有收到,发送方都会将消息头的DUP设置为1,然后再次发送消息,消息最少一次到达服务。例如网络延迟等问题,发布者重复发送消息,订阅者多次订阅重复消息 

  • Qos = 2  只有一次的传输

  其实Qos = 2 只是在 1 的基础上做了改掉的赶脚,在发布者PUBLISH到服务器之后多了消息的确认以及多了消息msgID的缓存,重复信息的去重。在服务器PUBLISH到订阅者之后也多了消息的确认。

  三种情况的区别

   0 没有保存message,没有重发机制,啥事也不知道,1和2 的发布者和服务器有保存message,发布者有重发机制,服务器都有PUBLISH之后的PUBACK的确认机制,但是2的服务器多了缓存msgID的一项功能,提供了去重功能,防止了消息的重复发送,以及消息的接收的确认机制。订阅者这边不过多的介绍,感兴趣再去了解。


 MQTT1.2.1版本出现的问题 

  问题的描述:因为项目中使用MQTT通信的地方比较多,一般都是以Qos = 0 的形式,这段时间发现会时常提醒报错Too many publishes in progress (32202),看了一下源码报错地方

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Mosquitto订阅端解析MQTT消息的JSON格式,你可以使用C语言中的标准库和第三方库来实现。以下是一个示例代码,演示了如何使用Mosquitto库订阅MQTT主题,并解析接收到的JSON消息: ```c #include <stdio.h> #include <stdlib.h> #include <mosquitto.h> #include <cJSON.h> #define MQTT_ADDRESS "mqtt.example.com" #define MQTT_PORT 1883 #define MQTT_TOPIC "sensors" // Mosquitto回调函数,用于处理连接成功、消息接收和连接断开时的事件 void on_connect(struct mosquitto *mosq, void *userdata, int result) { if(result == 0) { printf("Connected to MQTT broker\n"); mosquitto_subscribe(mosq, NULL, MQTT_TOPIC, 0); } else { fprintf(stderr, "Connect failed: %s\n", mosquitto_strerror(result)); } } void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message) { if(message->payloadlen > 0) { // 解析JSON消息 cJSON *root = cJSON_Parse(message->payload); if(root == NULL) { fprintf(stderr, "Failed to parse JSON message\n"); return; } // 从JSON中提取数据 cJSON *file_content = cJSON_GetObjectItem(root, "file_content"); if(file_content != NULL && file_content->type == cJSON_String) { printf("Received file content: %s\n", file_content->valuestring); } // 释放JSON对象 cJSON_Delete(root); } } void on_disconnect(struct mosquitto *mosq, void *userdata, int rc) { printf("Disconnected from MQTT broker\n"); } int main() { // 初始化Mosquitto库 mosquitto_lib_init(); // 创建Mosquitto客户端实例 struct mosquitto *mosq = mosquitto_new(NULL, true, NULL); if(mosq == NULL) { fprintf(stderr, "Failed to create Mosquitto instance\n"); mosquitto_lib_cleanup(); return 1; } // 设置连接、消息接收和连接断开的回调函数 mosquitto_connect_callback_set(mosq, on_connect); mosquitto_message_callback_set(mosq, on_message); mosquitto_disconnect_callback_set(mosq, on_disconnect); // 连接到MQTT代理服务器 int rc = mosquitto_connect(mosq, MQTT_ADDRESS, MQTT_PORT, 0); if(rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Connect failed: %s\n", mosquitto_strerror(rc)); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); return 1; } // 循环处理MQTT事件 while(mosquitto_loop(mosq, 0, 1) == MOSQ_ERR_SUCCESS) {} // 释放资 mosquitto_destroy(mosq); mosquitto_lib_cleanup(); return 0; } ``` 在上述示例中,我们使用Mosquitto库订阅了一个MQTT主题,并设置了连接、消息接收和连接断开的回调函数。 在`on_message`回调函数中,我们首先将收到的MQTT消息的payload(即消息内容)解析为JSON对象。然后,我们可以使用cJSON库从JSON对象中提取所需的数据。在示例中,我们提取了名为`file_content`的字符串键值对。 最后,我们在`main`函数中循环处理MQTT事件,以保持与MQTT代理服务器的连接。当收到订阅的主题上的消息时,将触发`on_message`回调函数进行解析和处理。 请确保在编译和运行代码之前,你已正确安装了所需的Mosquitto库和cJSON库,并将相关的头文件和库文件包含到你的项目中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值