初识MQTT+EMQX(Java连接EMQX)

1. 简介

  • MQTT

        MQTT 是物联网 (IoT) 的 OASIS 标准消息传递协议。它被设计为一种极其轻量级的发布/订阅消息传递传输

非常适合以较小的代码占用空间和最小的网络带宽连接远程设备。

发布订阅架构:

MQTT 的核心是MQTT 代理和 MQTT 客户端。MQTT 代理是发送者和接收者之间的中介,负责将消息分发给适当的接收者。MQTT 客户端向代理发布消息,其他客户端则订阅特定主题以接收消息。每条 MQTT 消息都包含一个主题,客户端会订阅自己感兴趣的主题。MQTT 代理会维护一个订阅者列表,并使用该列表将消息传递给相关客户端。

MQTT 代理还可以为断开连接的客户端缓冲消息,确保即使在网络不稳定的情况下也能可靠地传递消息。为了实现这一点,MQTT 支持三种不同的服务质量(QoS) 级别:0(最多一次)、1(至少一次)和 2(恰好一次)。

MQTT 规范有两个版本:MQTT 3.1.1 和 MQTT 5。虽然大多数商业 MQTT 代理现在都支持 MQTT 5,但一些 IoT 管理云服务仍然主要支持 MQTT 3.1.1。 

其他的相关特性以及使用说明可参考:MQTT从入门到入土

  • EMQX

        EMQX 是一款开源的大规模分布式 MQTT 消息服务器,功能丰富,专为物联网和实时通信应用而设计。EMQX 5.0 单集群支持 MQTT 并发连接数高达 1 亿条,单服务器的传输与处理吞吐量可达每秒百万级 MQTT 消息,同时保证毫秒级的低时延。

        EMQX 支持多种协议,包括 MQTT (3.1、3.1.1 和 5.0)、HTTP、QUIC 和 WebSocket 等,保证各种网络环境和硬件设备的可访问性。EMQX 还提供了全面的 SSL/TLS 功能支持,比如双向认证以及多种身份验证机制,为物联网设备和应用程序提供可靠和高效的通信基础设施。

 

相关特性介绍可参考:EMQX指南 

 

 2. 实例

        2.1 目标

        通过Java+MQTT 5.0协议发送消息到emqx,客户端订阅主题获取到该条消息做处理逻辑。

        2.2 tool

工具

版本

JDK

22.0.2

MQTT

v5

Maven

v3.6.3

 

        2.3 相关依赖

<properties>
    <maven.compiler.source>22</maven.compiler.source>
    <maven.compiler.target>22</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>


<dependency>
    <groupId>org.eclipse.paho</groupId>
    <artifactId>org.eclipse.paho.mqttv5.client</artifactId>
    <version>1.2.5</version>
</dependency>

 

        2.4 源码

package org.example;


import org.eclipse.paho.mqttv5.client.*;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;

/**
 * Author:yang
 * Date:2024-08-09 9:31
 */

public class Main {
    private static final String BROKER_URL = "tcp://110.41.55.242:1883";
    private static final String TOPIC = "thing/product/data";

    private MqttClient sampleClient;

    public static void main(String[] args) {
        Main test = new Main();
        try {
            test.connectAndTest();
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

    public void connectAndTest() throws MqttException {
        sampleClient = new MqttClient(BROKER_URL, "sample-client");

        try {
            // 设置连接选项
            MqttConnectionOptions options = new MqttConnectionOptions();
            options.setCleanStart(false);
            // 连接到MQTT代理服务器
            sampleClient.connect(options);

            // 创建回调接口
            MqttCallback callback = new MqttCallback() {

                @Override
                public void disconnected(MqttDisconnectResponse mqttDisconnectResponse) {
                    System.out.println("Connection lost: " + mqttDisconnectResponse.getReasonString());
                }

                @Override
                public void mqttErrorOccurred(MqttException e) {
                    System.out.println("MQTT error occurred: " + e.getMessage());
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    System.out.println("Received message: " + new String(message.getPayload()) + " on topic: " + topic);
                }

                @Override
                public void deliveryComplete(IMqttToken iMqttToken) {

                }

                @Override
                public void connectComplete(boolean b, String s) {
                    System.out.println("Connected to MQTT broker: " + s);
                    // 订阅主题
                    try {
                        sampleClient.subscribe(TOPIC,1);
                    } catch (MqttException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("Subscribed to topic: " + TOPIC);
                }

                @Override
                public void authPacketArrived(int i, MqttProperties mqttProperties) {

                }

            };

            // 设置回调
            sampleClient.setCallback(callback);

            // 取消订阅
            sampleClient.unsubscribe(TOPIC);
            System.out.println("Unsubscribed from topic: " + TOPIC);
            // 订阅主题
            sampleClient.subscribe(TOPIC,1);
            System.out.println("Subscribed to topic: " + TOPIC);

             //启动状态监控线程
            Thread statusMonitorThread = new Thread(this::monitorClientStatus);
            statusMonitorThread.start();

             //主线程将一直运行,保持应用程序活跃
            while (true) {
                // 这里可以执行其他任务,或者简单地休眠
                Thread.sleep(15000);
                //sampleClient.disconnectForcibly(2);
                System.out.println("close client");
                sampleClient.close(true);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 确保客户端关闭
            if (sampleClient != null && sampleClient.isConnected()) {
                try {
                    sampleClient.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void monitorClientStatus() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                System.out.println("MQTT client status: " + sampleClient.isConnected());
                // 检查MQTT客户端是否连接
                if (!sampleClient.isConnected()) {
                    System.out.println("MQTT client is not connected, attempting to reconnect.");
                    // 尝试重新连接
                    try {
                        sampleClient.connect();
                    } catch (MqttException e) {
                        System.out.println("Failed to reconnect: " + e.getMessage());
                        // 可以选择在这里处理重连失败的情况,例如重试或退出
                    }
                }
                // 适当休眠,避免CPU过载
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // 线程被中断,退出循环
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                System.out.println("Error while monitoring MQTT client status: " + e.getMessage());
            }
        }
    }
}

        2.5 注意事项

  • MQTT v3 和MQTT v5 在Java中API有点差异,更换协议某些接口代码也需要换;

  • 订阅主题,获取主题中的消息可以通过回调函数实现(messageArrived);

  • 当连接断开再次连接成功后,订阅的TOPIC清除了,需要重新订阅,可以通过(connectComplete,该方法在第一次连接后不会执行);

  • 如果需要从topic1发送的消息,通过topic2收到,中间需要做其他的操作,比如规则转换。

注:这个示例可以结合文件切片实现跨网文件传输

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值