实战:软件架构网络系列之【 MQTT V5基础功能:MQTT 5.0 发布和订阅 】

概叙

科普文:软件架构网络系列之【应用层协议: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 Mosquittotest.mosquitto.org1883 (TCP) 8883 (SSL) 8080 (WebSocket)MQTT 3.1.1 / 5.0由 Eclipse 基金会维护,适合测试
HiveMQ Publicbroker.hivemq.com1883 (TCP) 8000 (WebSocket)MQTT 3.1.1支持 WebSocket,适合 Web 应用
EMQX Publicbroker.emqx.io1883 (TCP) 8083 (WebSocket)MQTT 3.1.1 / 5.0支持 MQTT 5.0
MQTTX Brokerbroker.mqttx.io1883 (TCP) 8084 (WebSocket)MQTT 3.1.1由 MQTTX 团队提供
Shiftr.iopublic.cloud.shiftr.io1883 (TCP) 8883 (SSL)MQTT 3.1.1需注册免费账号
Adafruit IOio.adafruit.com1883 (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. 回调扩展:当前订阅者的回调仅打印消息内容,实际项目可根据需求处理消息(如存储到数据库、触发业务逻辑等)。

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

01Byte空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值