概叙
科普文:软件架构网络系列之【应用层协议:MQTT(消息队列遥测传输)详解】-CSDN博客
科普文:软件架构网络系列之【在线公共 MQTT 服务器梳理】-CSDN博客
实战:软件架构网络系列之【 MQTT V3工具类:MqttClientV3Util】-CSDN博客
实战:软件架构网络系列之【 MQTT基层功能:发布/订阅】-CSDN博客
实战:软件架构网络系列之【 MQTT基层功能:MQTT遗嘱消息(可靠传输保障)】-CSDN博客
实战:软件架构网络系列之【 MQTT基层功能:带遗嘱消息的智能家居温度传感器(可靠传输保障)】-CSDN博客
实战:软件架构网络系列之【 MQTT基础功能:MQTT over SSL/TLS 安全通信(安全传输)】-CSDN博客
实战:软件架构网络系列之【 MQTT基础功能:MQTT 重连(可靠传输保障)】-CSDN博客
实战:软件架构网络系列之【MQTT基础功能:MQTT多主题订阅】-CSDN博客
实战:软件架构网络系列之【 MQTT V5工具类:MqttClientV5Util】-CSDN博客
【摘要】本系列文章全面解析MQTT协议及其应用实践。
基础篇详细介绍了MQTT作为轻量级发布/订阅协议的特性,并整理了6个主流公共MQTT服务器(如Mosquitto、HiveMQ等)的地址端口信息。实战篇包含:1)开发MqttClientV3/V5工具类简化客户端操作;2)实现多主题订阅与发布功能;3)通过遗嘱消息保障可靠传输;4)构建智能家居传感器案例;5)配置SSL/TLS安全通信。
特别提供了MQTT5.0工具类实现,支持用户属性等新特性,包含连接管理、异常处理等完整功能,适用于物联网开发场景。文中还对比了各公共Broker的协议支持情况,为开发者提供实用参考。
免费公共 MQTT Broker
Broker 名称 | 地址 | 端口 | 协议支持 | 备注 |
---|---|---|---|---|
Eclipse Mosquitto | test.mosquitto.org | 1883 (TCP) 8883 (SSL) 8080 (WebSocket) | MQTT 3.1.1 / 5.0 | 由 Eclipse 基金会维护,适合测试 |
HiveMQ Public | broker.hivemq.com | 1883 (TCP) 8000 (WebSocket) | MQTT 3.1.1 | 支持 WebSocket,适合 Web 应用 |
EMQX Public | broker.emqx.io | 1883 (TCP) 8083 (WebSocket) | MQTT 3.1.1 / 5.0 | 支持 MQTT 5.0 |
MQTTX Broker | broker.mqttx.io | 1883 (TCP) 8084 (WebSocket) | MQTT 3.1.1 | 由 MQTTX 团队提供 |
Shiftr.io | public.cloud.shiftr.io | 1883 (TCP) 8883 (SSL) | MQTT 3.1.1 | 需注册免费账号 |
Adafruit IO | io.adafruit.com | 1883 (TCP) 8883 (SSL) | MQTT 3.1.1 | 需 API Key(免费额度) |
MQTT V5工具类:MqttClientV5Util
MqttClientV5Util封装了MQTT 5.0客户端的创建、连接和关闭操作,支持默认与自定义配置。
主要功能包括:获取客户端实例、设置连接参数(如clean start、keep alive等)、建立连接及安全断开连接。工具类简化了MQTT客户端的使用流程。
实战:软件架构网络系列之【 MQTT V5工具类:MqttClientV5Util】-CSDN博客
MQTT V5基础功能:MQTT 5.0 发布和订阅
下面Java代码演示了使用MQTT 5.0协议进行消息发布与订阅的基本流程。
主要功能包括:创建发布者和订阅者客户端、连接MQTT Broker、订阅主题、接收并打印消息、发布一条测试消息,最后断开连接并释放资源。
package com.zxx.study.rjava.mqtt;
import com.zxx.study.common.util.ZhouxxTool;
import org.eclipse.paho.mqttv5.client.MqttClient;
import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;
import org.eclipse.paho.mqttv5.client.MqttDisconnectResponse;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
import org.eclipse.paho.mqttv5.common.packet.UserProperty;
import java.util.ArrayList;
import java.util.List;
/**
* MQTT 5.0 示例(发布者和订阅者分离)
*
* @author zhouxx
* @create 2024-10-10 13:31
*/
public class Mqtt5Example {
private static final String BROKER = "tcp://test.mosquitto.org:1883";
private static final String PUBLISHER_ID = "JavaMqtt5Publisher";
private static final String SUBSCRIBER_ID = "JavaMqtt5Subscriber";
private static final String TOPIC = "mqtt5/topic";
public static void main(String[] args) {
MqttClient publisher = null;
MqttClient subscriber = null;
try {
// 创建发布者客户端
publisher = MqttClientV5Util.getMqttClient(BROKER, PUBLISHER_ID);
MqttConnectionOptions pubOpts = new MqttConnectionOptions();
pubOpts.setCleanStart(false);
// 创建订阅者客户端
subscriber = MqttClientV5Util.getMqttClient(BROKER, SUBSCRIBER_ID);
// 连接发布者
ZhouxxTool.printTimeAndThread("发布者连接到broker: " + BROKER);
publisher.connect(pubOpts);
ZhouxxTool.printTimeAndThread("发布者已连接");
// 连接订阅者
ZhouxxTool.printTimeAndThread("订阅者连接到broker: " + BROKER);
//subscriber.connect(subOpts);
MqttClientV5Util.setMqttConnectionOptions(subscriber);
ZhouxxTool.printTimeAndThread("订阅者已连接");
// 设置订阅者回调
subscriber.setCallback(new org.eclipse.paho.mqttv5.client.MqttCallback() {
@Override
public void disconnected(MqttDisconnectResponse mqttDisconnectResponse) {
ZhouxxTool.printTimeAndThread("订阅者连接丢失: " + mqttDisconnectResponse.getException().getMessage());
}
@Override
public void mqttErrorOccurred(MqttException e) {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
ZhouxxTool.printTimeAndThread("订阅者收到消息: " + new String(message.getPayload()));
ZhouxxTool.printTimeAndThread("消息属性: " + message.getProperties());
}
@Override
public void deliveryComplete(org.eclipse.paho.mqttv5.client.IMqttToken token) {
// 订阅者不需要处理发送完成事件
}
@Override
public void connectComplete(boolean b, String s) {
}
@Override
public void authPacketArrived(int i, MqttProperties mqttProperties) {
}
});
// 订阅主题
ZhouxxTool.printTimeAndThread("订阅者订阅主题: " + TOPIC);
subscriber.subscribe(TOPIC, 1);
// 等待订阅建立
Thread.sleep(1000);
// 发布消息
String content = "MQTT 5.0 message from Java";
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(1);
ZhouxxTool.printTimeAndThread("发布者发布消息: " + content);
publisher.publish(TOPIC, message);
ZhouxxTool.printTimeAndThread("发布者已发布消息");
// 保持连接
Thread.sleep(5000);
} catch (MqttException | InterruptedException e) {
e.printStackTrace();
} finally {
// 清理资源
try {
if (subscriber != null && subscriber.isConnected()) {
subscriber.disconnect();
ZhouxxTool.printTimeAndThread("订阅者已断开连接");
subscriber.close();
ZhouxxTool.printTimeAndThread("订阅者客户端已关闭");
}
if (publisher != null && publisher.isConnected()) {
publisher.disconnect();
ZhouxxTool.printTimeAndThread("发布者已断开连接");
publisher.close();
ZhouxxTool.printTimeAndThread("发布者客户端已关闭");
}
} catch (MqttException e) {
e.printStackTrace();
}
}
}
}
该代码是一个完整的 MQTT 5.0 发布者-订阅者分离示例,通过清晰的代码结构和注释,展示了 MQTT 5.0 的基础通信流程(连接、订阅、发布、接收)及部分特性(如消息属性、回调处理),适合用于学习和验证 MQTT 5.0 客户端的基本功能,也可作为物联网或消息推送场景的入门参考。
核心功能
1. 角色分离:明确区分 发布者(Publisher) 和 订阅者(Subscriber),分别使用不同的客户端 ID(JavaMqtt5Publisher
和 JavaMqtt5Subscriber
),模拟真实场景中生产者和消费者的独立部署。
2. 主题订阅与发布:订阅者订阅指定主题(mqtt5/topic
,QoS=1),发布者向同一主题发布一条消息(QoS=1),验证消息的可靠传递。
3. MQTT 5.0 特性支持:订阅者通过回调获取消息的附加属性(如用户属性、内容类型等),并打印消息内容和属性信息。
4. 连接管理:发布者使用 CleanStart=false
保留会话状态(适用于需要恢复未确认消息的场景),订阅者使用默认配置(清理会话)。
5. 资源安全:在程序结束时,主动断开连接并关闭客户端,确保网络和内存资源释放。
主流程(main 方法)
按顺序执行以下步骤:
1. 创建客户端:分别初始化发布者(publisher
)和订阅者(subscriber
)客户端实例。
2. 配置连接选项:发布者设置 CleanStart=false
(保留会话状态),订阅者通过工具类 MqttClientV5Util.setMqttConnectionOptions
配置(含 MQTT 5.0 用户属性)。
3. 建立连接:发布者和订阅者依次连接到 MQTT 代理(test.mosquitto.org:1883
)。
4. 订阅主题:订阅者订阅主题 mqtt5/topic
(QoS=1,保证消息至少送达一次)。
5. 发布消息:发布者构造一条文本消息(QoS=1),发布到订阅的主题。
6. 消息处理:订阅者通过回调 messageArrived
接收消息,并打印消息内容及属性。
7. 保持运行:线程休眠 5 秒,确保订阅者有足够时间接收并处理消息。
8. 资源释放:在 finally
块中主动断开连接并关闭发布者与订阅者客户端。
设计亮点
1. 角色清晰分离:发布者和订阅者使用独立的客户端实例和线程(虽未显式用线程池,但逻辑上解耦),模拟真实生产环境中的生产者和消费者。
2. MQTT 5.0 特性支持:通过工具类配置用户属性(如优先级、版本号),订阅者可获取消息的附加元数据,为业务扩展提供可能(如消息优先级处理)。
private static final String BROKER = "tcp://test.mosquitto.org:1883"; // MQTT代理地址(非加密端口)
private static final String PUBLISHER_ID = "JavaMqtt5Publisher"; // 发布者客户端唯一标识
private static final String SUBSCRIBER_ID = "JavaMqtt5Subscriber"; // 订阅者客户端唯一标识
private static final String TOPIC = "mqtt5/topic"; // 订阅与发布的主题
- BROKER:使用公共测试 MQTT 代理(
test.mosquitto.org
的 1883 端口,非加密)。 - PUBLISHER_ID/SUBSCRIBER_ID:发布者和订阅者的唯一标识符(确保 MQTT 协议要求的客户端 ID 唯一性)。
- TOPIC:消息的主题(类似频道),发布者向该主题发送消息,订阅者从该主题接收消息。
只有这两个免费公共 MQTT Broker 支持 MQTT 5.0
3. 连接策略灵活:发布者保留会话状态(CleanStart=false
),适合需要可靠传递未确认消息的场景;订阅者使用默认配置(清理会话),适合简单订阅需求。
4. 异常与资源安全:通过 try-catch-finally
结构捕获异常并确保客户端断开连接和关闭,避免资源泄漏。
注意事项
1. 工具类依赖:MqttClientV5Util
为自定义工具类(需项目自行实现),推测封装了 MQTT 5.0 客户端的创建和连接配置逻辑(如设置用户属性、心跳间隔等)。
2. 测试环境限制:使用 tcp://test.mosquitto.org:1883
(非加密端口),适用于测试;生产环境需替换为加密代理(如 ssl://
协议)并配置安全参数(如证书、用户名/密码)。
3. 硬编码优化:代理地址、客户端 ID、主题等建议通过配置文件管理(如 application.properties
),提升灵活性。
4. 回调扩展:当前订阅者的回调仅打印消息内容,实际项目可根据需求处理消息(如存储到数据库、触发业务逻辑等)。