MQTT服务安装,测试,Java中的使用方法

MQTT介绍

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

Ubuntu安装 MQTT Mosquitto

  1. 引入mosquitto仓库并更新

    $sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
    $sudo apt-get update

  2. 执行以下命令安装mosquitto包

    $sudo apt-get install mosquitto

  3. 安装mosquitto开发包

    $sudo apt-get install libmosquitto-dev

  4. 安装mosquitto客户端

    $sudo apt-get install mosquitto-clients

  5. 查询mosquitto是否正确运行

    $sudo service mosquitto status
    在这里插入图片描述

mqtt.fx的安装和使用(测试工具)

目前最新版下载地址(支持windows,linux,mac)
http://www.jensd.de/apps/mqttfx/1.7.1/

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置好后选择对应的服务器,点击连接。
在这里插入图片描述

首先订阅某个主题的消息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MQTT 协议原理

在这里插入图片描述

MQTT协议实现方式

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。

MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:

(1)Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);
(2)payload,可以理解为消息的内容,是指订阅者具体要使用的内容。

网络传输与应用消息

MQTT会构建底层网络传输:它将建立客户端到服务器的连接,提供两者之间的一个有序的、无损的、基于字节流的双向传输。

当应用数据通过MQTT网络发送时,MQTT会把与之相关的服务质量(QoS)和主题名(Topic)相关连。

MQTT客户端

一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的网络连接。客户端可以:

(1)发布其他客户端可能会订阅的信息;
(2)订阅其它客户端发布的消息;
(3)退订或删除应用程序的消息;
(4)断开与服务器连接。

MQTT服务器

MQTT服务器以称为"消息代理"(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:

(1)接受来自客户的网络连接;
(2)接受客户发布的应用信息;
(3)处理来自客户端的订阅和退订请求;
(4)向订阅的客户转发应用程序消息。

MQTT协议中的订阅、主题、会话

一、订阅(Subscription)

订阅包含主题筛选器(Topic Filter)和最大服务质量(QoS)。订阅会与一个会话(Session)关联。一个会话可以包含多个订阅。每一个会话中的每个订阅都有一个不同的主题筛选器。

二、会话(Session)

每个客户端与服务器建立连接后就是一个会话,客户端和服务器之间有状态交互。会话存在于一个网络之间,也可能在客户端和服务器之间跨越多个连续的网络连接。

三、主题名(Topic Name)

连接到一个应用程序消息的标签,该标签与服务器的订阅相匹配。服务器会将消息发送给订阅所匹配标签的每个客户端。

四、主题筛选器(Topic Filter)

一个对主题名通配符筛选器,在订阅表达式中使用,表示订阅所匹配到的多个主题。

五、负载(Payload)

消息订阅者所具体接收的内容。

MQTT协议中的方法

MQTT协议中定义了一些方法(也被称为动作),来于表示对确定资源所进行操作。这个资源可以代表预先存在的数据或动态生成数据,这取决于服务器的实现。通常来说,资源指服务器上的文件或输出。主要方法有:

(1)Connect。等待与服务器建立连接。
(2)Disconnect。等待MQTT客户端完成所做的工作,并与服务器断开TCP/IP会话。
(3)Subscribe。等待完成订阅。
(4)UnSubscribe。等待服务器取消客户端的一个或多个topics订阅。
(5)Publish。MQTT客户端发送消息请求,发送完成后返回应用程序线程。

Java中的使用方法(举例)

MQClient

package com.xd.controller.app.mqttmodule.controller;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class MQClient {

    private static final Logger log = LoggerFactory.getLogger(MQClient.class);

    /**
     * mqtt客户端地址
     */
    private String mqClientConsumerAddress = "b018f035e2a04b7e906c2cd270e77c1a";
    /**
     * mqtt host地址
     */
    private String host = "tcp://114.***.**.**:1883";
    /**
     * 连接mqtt的用户名和密码,可以不用
     */
    private String mqttUserName = "";
    private String mqttPassword ="";
    private MqttClient client;
    private MqttConnectOptions options;

    private static volatile MQClient mqClient = null;

    private MQClient() {

    }

    /**
     * 创建单例模式,用户长连接
     * @return
     */
    public static MQClient getInstance() {
        if (null == mqClient) {
            synchronized (MQClient.class) {
                if (null == mqClient) {
                    return new MQClient();
                }
            }
        }
        return mqClient;
    }

    /**
     * @author sgm	
     * @date 2020-11-25
     * @description 创建服务
     *
     * @param
     * @return void
     **/
    public void creat2() {
        client = init();
        // 创建失败再创建一次
        if (null == client) {
            client = init();
        }
        connect();
    }
    /**
     * 创建MqttClient对象
     * @return
     */
    private MqttClient init() {
        try {
            // 使用当前时间点,确保客户端完全唯一
            String client = mqClientConsumerAddress + "_" + System.currentTimeMillis();
            return new MqttClient(host, client, new MemoryPersistence());
        } catch (MqttException e) {
            log.error(String.format("创建MqttClient失败:%s" , e.toString()));
        }
        return null;
    }

    private MqttConnectOptions getOptions() {
        // MQTT的连接设置
        options = new MqttConnectOptions();
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(true);
        // 设置连接的用户名
        String userName = mqttUserName;
        if (!StringUtils.isBlank(userName)) {
            options.setUserName(userName);
        }
        // 设置连接的密码
        String password = mqttPassword;
        if (!StringUtils.isBlank(password)) {
            options.setPassword(password.toCharArray());
        }
        // 设置超时时间 单位为秒
        options.setConnectionTimeout(10);
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options.setKeepAliveInterval(20);
        //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
        //options.setWill(topic, "close".getBytes(), 2, true);

        return options;

    }

    /**
     * @author sgm
     * @date 2020-11-25
     * @description  创建连接
     *
     * @param
     * @return void
     **/
    public void connect() {
        try {
            if (null != client) {
                log.info("连接MQTT服务器");
                client.connect(getOptions());
            }
        } catch (MqttException e) {
            int count = 0;
            int three = 3;
            // 重新连接三次,5秒连接一次
            while (count < three) {
                try {
                    log.error("连接失败,重新连接...%s", e);
                    client.connect(getOptions());
                    if (client.isConnected()) {
                        break;
                    } else {
                        Thread.sleep(10000);
                    }
                } catch (Exception e1) {
                    log.error("再次连接失败:", e1);
                } finally {
                    count ++;
                }
            }
        }
    }

    public boolean isConnected() {
        return mqClient.isConnected();
    }

    /**
     * @author sgm
     * @date 2020-11-25
     * @description  订阅消息
     *
     * @param topic 传入主题
     * @return void
     **/
    public void subMessage(String topic, int qos) {
        //订阅消息
        try {
            int[] qoses  = {qos};
            String[] topics = {topic};
            client.subscribe(topics, qoses);
        } catch (MqttException e) {
            log.error(String.format("订阅失败:%s", e.toString()));
        }
    }

    public MqttClient getClient() {
        return client;
    }

    /**
     * 发送消息
     * @param topic
     * @param qos
     * @param message
     */
    public void sendMessage(String topic, int qos, String message) {
        try {
            MqttMessage mqttMessage = new MqttMessage(message.getBytes());
            mqttMessage.setQos(qos);
            client.publish(topic, mqttMessage);
        } catch (MqttException e) {
            log.error("发送消息失败:", e);
        }
    }
}

发布消息的回调类

package com.xd.controller.app.mqttmodule.controller;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 发布消息的回调类
 * <p>
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
 * 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。
 * 在回调中,将它用来标识已经启动了该回调的哪个实例。
 * 必须在回调类中实现三个方法:
 * <p>
 * public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
 * <p>
 * public void connectionLost(Throwable cause)在断开连接时调用。
 * <p>
 * public void deliveryComplete(MqttDeliveryToken token))
 * 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
 * 由 MqttClient.connect 激活此回调。
 */

/**
 * @author : sgm
 * mqtt订阅消息后,回执处理
 */
public class IwCallBack implements MqttCallback {

    private Logger log = LoggerFactory.getLogger(IwCallBack.class);
    private MQClient mqClient = com.xd.controller.app.mqttmodule.controller.MQClient.getInstance();
    /**
     * 订阅的主题  C7C13795D7DD
     */
    private String topic = "dev/cloud/#";
    @Override
    public void connectionLost(Throwable cause) {
        log.error("mqtt重连", cause);
        // 连接丢失后,一般在这里面进行重连
        mqClient.connect();
        // 重连后重新订阅一次
        if (mqClient.isConnected()) {
            mqClient.subMessage(topic, 1);
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
    }

    public void messageArrived(String topic, org.eclipse.paho.client.mqttv3.MqttMessage message) throws Exception {
        /**
         * 获取到mqtt传输过来的消息,多线程处理解析消息,避免阻塞
         */
    	
        System.out.println(message.toString());

    }
}

测试订阅某主题

package com.xd.controller.app.mqttmodule.controller;


/**
 * @author :  sgm
 * @description :
 * @createDate :  2020-11-25
 * <p>
 * maven引入jar包
 *
 * <dependency>
 * <groupId>org.eclipse.paho</groupId>
 * <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
 * <version>1.2.0</version>
 * </dependency>
 */
public class TestMqtt {

    public static void main(String[] args) {
    	com.xd.controller.app.mqttmodule.controller.MQClient mqClient = MQClient.getInstance();
        mqClient.creat2();
        IwCallBack iwCallBack = new IwCallBack();
        /**
         * 订阅的topic   C7C13795D7DD
         */
        String topic = "dev/cloud/#";
        mqClient.getClient().setCallback(iwCallBack);
        mqClient.subMessage(topic.toLowerCase(), 1);
    }
}

成功返回结果

在这里插入图片描述

订阅成功返回结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,常用于物联网设备之间的通信。在Java,可以使用Eclipse Paho库来实现MQTT协议的代码。 以下是一个简单的Java代码示例,演示了如何使用Eclipse Paho库实现MQTT协议的发布和订阅功能: 1. 首先,需要导入Eclipse Paho库的相关依赖。可以在Maven项目添加以下依赖项: ```xml <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> ``` 2. 发布消息的代码示例: ```java import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; public class MqttPublisher { public static void main(String[] args) { String broker = "tcp://mqtt.eclipse.org:1883"; String topic = "test/topic"; String message = "Hello, MQTT!"; try { MqttClient client = new MqttClient(broker, MqttClient.generateClientId()); client.connect(); MqttMessage mqttMessage = new MqttMessage(message.getBytes()); client.publish(topic, mqttMessage); client.disconnect(); } catch (MqttException e) { e.printStackTrace(); } } } ``` 3. 订阅消息的代码示例: ```java import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class MqttSubscriber { public static void main(String[] args) { String broker = "tcp://mqtt.eclipse.org:1883"; String topic = "test/topic"; try { MqttClient client = new MqttClient(broker, MqttClient.generateClientId(), new MemoryPersistence()); client.connect(); client.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { System.out.println("Connection lost!"); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("Received message: " + new String(message.getPayload())); } @Override public void deliveryComplete(IMqttDeliveryToken token) { // Not used in this example } }); client.subscribe(topic); } catch (MqttException e) { e.printStackTrace(); } } } ``` 以上代码示例,发布者使用`MqttClient`类连接到指定的MQTT代理(broker),并通过`publish`方法发布消息到指定的主题(topic)上。订阅者使用`MqttClient`类连接到MQTT代理,并通过`subscribe`方法订阅指定的主题。当有新消息到达时,通过设置的回调函数(`MqttCallback`)进行处理。 注意:以上示例使用MQTT代理是公共可用的测试代理,仅供演示目的使用。在实际应用,需要根据实际情况配置和使用自己的MQTT代理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值