mqtt消息队列的使用mosquitto安装配置代码示例

在物联网时代,mqtt消息队列经常用作设备与上层应用系统的通信中介,因为最近项目多数使用mqtt server,故写文记之。

mosquitto 是开源的轻量级消息队列。提供c、python、java等多种客户端。使用过程如下:

https://github.com/eclipse/mosquitto

sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients
sudo systemctl start mosquitto
sudo systemctl enable mosquitto

服务端指令
1)查看状态
sudo service mosquitto status
2)启动服务器
sudo service mosquitto start
3)关闭服务器
sudo service mosquitto stop

mosquitto:代理器主程序
mosquitto.conf:配置文件【路径:/etc/mosquitto】
mosquitto_passwd:用户密码管理工具
mosquitto_pub:用于发布消息的命令行客户端
mosquitto_sub:用于订阅消息的命令行客户端
mqtt:MQTT的后台进程
libmosquitto:客户端编译的库文件

MQTT的基本概念
Broker:消息代理服务器,负责接收和分发消息。
Client:客户端,可以是发布者或订阅者。
Topic:消息主题,客户端通过订阅特定主题来接收消息。
QoS(Quality of Service):服务质量等级,定义消息传输的可靠性。

MQTT提供三种服务质量(Quality of Service,简写QoS),供开发者根据不同的情景选择不同的服务级别:
QoS0:最多发送一次消息,在消息发送出去后,接收者不会发送回应,发送者也不会重发消息。
QoS1:最少发送一次消息(消息最少需要送达一次,也有可送达多次), QoS 1的 PUBLISH 报文的可变报头中包含一个报文标识符,需要 PUBACK 报文确认。
QoS2:这是最高等级的服务质量,消息丢失和重复都是不可接受的。

可以使用paho-mqtt库在Python中实现MQTT客户端。

安装paho-mqtt库
pip install paho-mqtt

python程序

import paho.mqtt.client as mqtt

broker = "192.168.1.175"
topic = "test/topic"
username = "admin"
password = "admin"


# 回调函数:连接成功
def on_connect(client, userdata, flags, rc):
    print(f"连接结果:{rc}")
    client.subscribe(topic=topic, qos=1)  # 订阅主题


# 回调函数:接收到消息
def on_message(client, userdata, msg):
    # 这里是业务处理消息,这里简单打印
    print(f"接收到消息:{msg.topic} {msg.payload.decode()}")


def main():
    # 创建 MQTT 客户端实例
    client = mqtt.Client()

    # 设置用户名和密码
    client.username_pw_set(username, password)

    # 指定连接成功和消息回调函数
    client.on_connect = on_connect
    client.on_message = on_message

    # 连接到 MQTT 代理
    client.connect(broker, 1883, 60)  # 假设 Mosquitto 运行在本地,端口为 1883

    # 启动网络循环,等待接收消息
    client.loop_forever()


if __name__ == "__main__":
    main()


客户端要先运行起来
import paho.mqtt.client as mqtt

broker = "192.168.1.175"
topic = "test/topic"
message = "Hello, MQTT,123  "
username = "test"
password = "test"

client = mqtt.Client()


client.username_pw_set(username, password)
client.connect(host=broker, port=1883)


# 发布消息
for i in range(10):
  client.publish(topic=topic, payload=message, qos=1)
client.disconnect()

配置文件
vi /etc/mosquitto/mosquitto.conf
示例

pid_file /run/mosquitto/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d


# 禁止匿名访问
allow_anonymous true
# # 认证配置,即登录账号信息的文件

password_file /etc/mosquitto/passwd

# # 权限配置
#acl_file /etc/mosquitto/aclfile
# # 监听的端口
listener 1883 0.0.0.0

在这里插入图片描述

配置用户名和密码:
sudo mosquitto_passwd -c /etc/mosquitto/passwd [username变量]
-c 会生成密码文件,不加-c 代表已有文件,只增加用户,第二次配置不需要输入-c
passwd :指定密码文件,将在当前目录下生成的文件名
username :指定配置的用户名,如whb

命令行发布消息示例:
mosquitto_pub -h localhost -u “whb” -p “whb” -t “test/topic” -m “Hello, MQTT”

java 消息发布与订阅

依赖:

<!--mqtt连接相关-->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>

		<dependency>
			<groupId>org.eclipse.paho</groupId>
			<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
			<version>1.2.5</version>
		</dependency>
		<!--ssl相关,如果不使用ssl连接可以不引入 -->
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcpkix-jdk15on</artifactId>
			<version>1.70</version>
		</dependency>
package com.cloud.mq;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.stereotype.Component;

/**
 * MQTT工具类
 */
@Slf4j
@Component
public class MQTTConnect {

    private String HOST = "tcp://127.0.0.1:1883"; //mqtt服务器的地址和端口号
    private final String clientId = "Test";
    private final String username = "test";
    private final String password = "123456";
    private MqttClient mqttClient;

    /**
     * 测试订阅消息
     */
    public static void main(String[] args) throws Exception {
        MQTTConnect mqttConnect = new MQTTConnect();
        mqttConnect.start();
        //订阅消息
        mqttConnect.sub("/topic/test1",0);
    }

    public void start() throws MqttException {
        // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
        mqttClient = new MqttClient(HOST, clientId + System.currentTimeMillis(), new MemoryPersistence());
        // MQTT的连接设置
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        // 设置超时时间 单位为秒
        options.setConnectionTimeout(10);///默认:30
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(false);//默认:true
        // 设置断开后重新连接(设置为true时将启用自动重新连接)
        options.setAutomaticReconnect(true);//默认:false
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options.setKeepAliveInterval(20);//默认:60
        // 设置回调
        mqttClient.setCallback(new Callback());
        mqttClient.connect(options);
    }

    /**
     * 自定义mqtt连接
     * @param host
     * @param clientId
     * @param userName
     * @param passWord
     * @param connectionTimeout
     * @param cleanSession
     * @param automaticReconnect
     * @param keepAliveInterval
     * @param mqttCallback
     * @throws MqttException
     */
    public void start(String host,String clientId, String userName, String passWord,
                      int connectionTimeout, boolean cleanSession,boolean automaticReconnect,
                      int keepAliveInterval,MqttCallback mqttCallback) throws MqttException {
        // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
        mqttClient = new MqttClient(host, clientId + System.currentTimeMillis(), new MemoryPersistence());
        // MQTT的连接设置
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(userName);
        options.setPassword(passWord.toCharArray());
        // 设置超时时间 单位为秒
        options.setConnectionTimeout(connectionTimeout);///默认:30
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(cleanSession);//默认:true
        // 设置断开后重新连接(设置为true时将启用自动重新连接)
        options.setAutomaticReconnect(automaticReconnect);//默认:false
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options.setKeepAliveInterval(keepAliveInterval);//默认:60
        // 设置回调
        mqttClient.setCallback(mqttCallback);
        mqttClient.connect(options);
    }

    /**
     * 关闭MQTT连接
     */
    public void close() throws MqttException {
        mqttClient.disconnect();
        mqttClient.close();
    }

    /**
     * 向某个主题发布消息 默认qos:1
     *
     * @param topic:发布的主题
     * @param msg:发布的消息
     */
    public void pub(String topic, String msg) throws MqttException {
        MqttMessage mqttMessage = new MqttMessage();
        //mqttMessage.setQos(2);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 向某个主题发布消息
     *
     * @param topic: 发布的主题
     * @param msg:   发布的消息
     * @param qos:   消息质量    Qos:0、1、2
     */
    public void pub(String topic, String msg, int qos) throws MqttException {
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(qos);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 订阅某一个主题 ,此方法默认的的Qos等级为:1
     *
     * @param topic 主题
     */
    public void sub(String topic) throws MqttException {
        mqttClient.subscribe(topic);
    }

    /**
     * 订阅某一个主题,可携带Qos
     *
     * @param topic 所要订阅的主题
     * @param qos   消息质量:0、1、2
     */
    public void sub(String topic, int qos) throws MqttException {
        mqttClient.subscribe(topic, qos);
    }
}

主题订阅与消息处理,这里只是简单打印消息,messageArrived就是你重点关注的方法。
针对物联网,应该对每个设备id作为主题,同一主题下,还应该传命令编号,把设备各种操作定义为不同的命令编号。

package com.cloud.mq;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * 常规MQTT回调函数
 * MqttCallback 接口定义了用于处理 MQTT 客户端异步事件的方法。
 * 当使用 Eclipse Paho MQTT 客户端库时,你可以实现这个接口来接收连接状态的变化和消息传递的通知。
 */
@Slf4j
public class Callback implements MqttCallback {

    /**
     * MQTT 断开连接会执行此方法
     *
     * 方法说明:当客户端与 MQTT 服务器之间的连接丢失时,此方法被调用。
     * @param throwable 表示导致连接丢失的原因,通常为一个 Throwable 对象
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("断开了MQTT连接 :{}", throwable.getMessage());
        log.error(throwable.getMessage(), throwable);
    }

    /**
     * publish发布成功后会执行到这里
     *
     * 方法说明:当一个消息的交付完成并且所有必要的确认都已收到时,此方法被调用。
     * 注意事项:
     * 对于 QoS 0 消息,在消息被网络层接收后会调用此方法。
     * 对于 QoS 1 消息,在接收到 PUBACK 包后调用此方法。
     * 对于 QoS 2 消息,在接收到 PUBCOMP 包后调用此方法。
     * @param iMqttDeliveryToken the delivery token associated with the message.
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.info("发布消息成功");
    }


    /**
     * subscribe订阅后得到的消息会执行到这里
     *
     * 方法说明:当从服务器接收到一条新消息时,此方法被调用
     * 注意事项:
     * 在此方法中抛出任何异常将会导致客户端关闭,并且未确认的消息可能会被重新发送。
     * 如果在此方法执行期间有其他消息到达,它们将被缓存直到此方法返回。
     * @param topic 消息发布的主题名称
     * @param message 实际的消息内容,类型为 MqttMessage
     * @throws Exception
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("收到来自 " + topic + " 的消息:{}", new String(message.getPayload()));
    }
}

此外消息通信还可以设置ssl,又分单向和双向ssl认证,需要制作CA证书。
注意,双向ssl认证,制作证书时,需要配置域名或ip,可参考文章:java连接mqtt(tcp、ssl单双向)
配置文件类似:

tls_version tlsv1.2

# 开启双向认证
require_certificate true
# CA证书路径
cafile /etc/mosquitto/ca.crt
# server证书路径
certfile /etc/mosquitto/server.crt
# server私钥路径
keyfile /etc/mosquitto/server.key

关于消息队列,网上例子很多,有c、java、python各种版本都有。
流行使用的消息服务主要是 kafka 、rocketMQ、MQtt Server、rabbitMQ,需要掌握的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

最好Tony

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

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

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

打赏作者

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

抵扣说明:

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

余额充值