MQTT协议

概述

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

MQTT应用场景

智能家居,汽车出行,工业制造,能源电力,智慧农业,医疗保健等领域

MQTT优点

  1. 轻量级和高效性:MQTT 是一种轻量级协议,设计用于在资源受限的设备和低带宽网络上运行。它的消息头非常小,协议本身也非常简单,因此可以在各种设备上高效地运行,包括传感器、嵌入式系统和移动设备。

  2. 发布/订阅模式:MQTT 使用发布/订阅模式,使得通信变得高度灵活和可扩展。设备可以通过订阅感兴趣的主题来接收消息,而不需要知道消息的发送者,这简化了系统架构并提高了通信效率。

  3. 可靠性:MQTT 提供了不同级别的服务质量(QoS),包括至多一次、至少一次和恰好一次交付保证。这使得开发人员可以根据应用的需求选择适当的服务质量级别,从而实现可靠的消息传递。

  4. 异步通信:MQTT 支持异步通信,设备可以随时发送消息而不必等待对方的响应。这种异步通信模式非常适用于需要实时性的应用场景,例如实时监控和控制系统。

  5. 断线重连和持久性会话:MQTT 客户端支持断线重连和持久性会话功能,这意味着设备可以在断开连接后自动重新连接到服务器,并且可以保持之前的会话状态,确保消息不会丢失。

  6. 灵活的主题结构:MQTT 的主题结构非常灵活,允许开发人员根据应用需求定义自己的主题层次结构。这种灵活性使得消息的组织和管理变得更加简单和有效。

  7. 跨平台支持:MQTT 是一个开放的标准,已经被广泛实现在各种不同的平台上,包括开源实现和商业实现。这使得开发人员可以轻松地在不同的设备和系统之间进行通信。

MQTT工作原理

MQTT客户端

客户端是指与 MQTT 服务器(也称为 MQTT 代理或代理服务器)进行通信的任何设备或应用程序。客户端可以是发布者(Publisher)、订阅者(Subscriber)或同时兼具发布者和订阅者的角色。

MQTT服务器端(MQTT Broker )

MQTT 服务器端,也称为 MQTT 代理(broker)或 MQTT 代理服务器,是负责接收、处理和转发 MQTT 消息的中间件组件。它是 MQTT 通信架构中的核心部分,负责管理客户端连接、维护订阅关系、处理消息传递等任务。

发布(Publish)/订阅(Subscribe)模式

  1. 发布者(Publisher)

    • 发布者是消息的发送方,负责将消息发布到 MQTT 服务器。

    • 发布者不直接发送消息给特定的接收方,而是将消息发布到一个或多个主题(Topic)。

    • 主题是消息的逻辑标识符,用于对消息进行分类和过滤。

  2. 订阅者(Subscriber)

    • 订阅者是消息的接收方,负责订阅感兴趣的主题,并接收相应的消息。

    • 订阅者向 MQTT 服务器发送订阅请求,指定它希望接收的主题。

    • 当有新消息发布到订阅者订阅的主题时,订阅者会收到该消息。

  3. 通信过程

    • 发布者发布消息时,指定一个或多个主题,并将消息发送到 MQTT 服务器。

    • MQTT 服务器接收到消息后,根据发布者指定的主题,将消息传递给所有订阅了相应主题的订阅者。

    • 订阅者收到消息后进行处理,例如更新数据、执行操作等。

  4. 灵活性和可扩展性

    • 发布/订阅模式使得通信变得高度灵活和可扩展。发布者和订阅者之间解耦,不需要直接知道彼此的存在,因此系统架构更加灵活。

    • 发布者和订阅者可以动态地加入和退出,而不会对系统的其他部分造成影响。

主题(topic)

主题(Topic)是消息的逻辑标识符,用于对消息进行分类和过滤。主题是发布者和订阅者之间通信的关键部分之一。

  1. 层次结构

    • MQTT 主题可以采用层次结构,使得主题具有父子关系。

    • 例如,主题可以类似于 "sensor/temperature"、"home/livingroom/lights",其中 "sensor" 和 "home" 是父级主题,"temperature" 和 "livingroom/lights" 是子级主题。

  2. 通配符

    • MQTT 主题支持两种通配符:单层通配符(+)和多层通配符(#)。

    • 单层通配符(+)匹配一个层级,多层通配符(#)匹配零个或多个层级。

    • 例如,主题 "sensor/+/temperature" 可以匹配 "sensor/kitchen/temperature" 和 "sensor/livingroom/temperature",而主题 "home/#" 可以匹配 "home/livingroom/lights" 和 "home/kitchen/temperature" 等。

      注意:通配符主题只能用于订阅,不能用于发布。

MQTT使用

常见的 MQTT 服务器或 MQTT 代理软件

  1. Eclipse Mosquitto

    • Eclipse Mosquitto 是一个开源的 MQTT 代理软件,它提供了基本的 MQTT 功能,包括发布/订阅机制、QoS 服务质量级别支持、身份认证和访问控制等。

    • Mosquitto 是一个轻量级的 MQTT 代理软件,由于其轻量级和简单易用的特点,Eclipse Mosquitto 适合用于中小型的 IoT 应用、传感器网络、家庭自动化等场景。

    官方网站:Eclipse Mosquitto

    docker安装

    1. 拉取 Mosquitto 镜像

      打开终端,执行以下命令拉取 Eclipse Mosquitto 镜像:

      docker pull eclipse-mosquitto

      这会从 Docker Hub 上拉取最新版本的 Eclipse Mosquitto 镜像。

    2. 创建 Mosquitto 配置文件

      在你的工作目录中创建一个名为 mosquitto.conf 的配置文件,并填写 Mosquitto 的配置。以下是一个简单的示例配置文件:

      listener 1883
      allow_anonymous true
      ​
      persistence true
      persistence_location /mosquitto/data/

      这个配置文件指定了 Mosquitto 监听端口为 1883,并启用了持久化存储,并将持久化数据保存在容器内的 /mosquitto/data/ 目录中。

    3. 运行 Mosquitto 容器

      执行以下命令创建并运行 Mosquitto 容器,同时将你创建的配置文件挂载到容器内的 /mosquitto/config/ 目录下:

      docker run -d --name mosquitto -p 1883:1883 -v /path/to/mosquitto.conf:/mosquitto/config/mosquitto.conf eclipse-mosquitto

      请将 /path/to/mosquitto.conf 替换为你创建的配置文件的路径。

  2. EMQ X

    • EMQ X 是一个开源的、高性能的 MQTT 代理软件,提供了丰富的功能和插件系统,它支持 MQTT 3.1、3.1.1 和 5.0 版本的协议,并提供了高可用性、水平扩展和集群功能。

    • EMQ X 还提供了丰富的插件系统,可以扩展其功能,如支持 CoAP、WebSocket、AMQP 等协议。

    • EMQ X 适用于需要高性能、高可用性和可伸缩性的场景,如工业物联网、智能城市、大规模传感器网络等。

    官方网站:EMQX: The #1 MQTT Platform for IoT, IIoT and Connected Cars

    在docker中使用:

    1.Get Docker Image

    docker pull emqx/emqx:5.5.0

    2.Start Docker Container

    docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.5.0

  3. HiveMQ

    • HiveMQ 是一个专业的 MQTT 代理软件,提供了高性能、高可靠性和安全性,它支持 MQTT 3.1、3.1.1 和 5.0 版本的协议,并提供了广泛的集成和管理功能。

    • HiveMQ 还提供了企业级功能,如集群、多数据中心复制、数据持久化等。

    • HiveMQ 适用于需要企业级功能和高度可靠性的场景,如金融、医疗、智能交通等对消息传递有严格要求的行业。

    官方网站:HiveMQ – The Most Trusted MQTT platform to Transform Your Business

    Download and run HiveMQ:

    Running the HiveMQ trial with Docker is the simplest way to experiment with HiveMQ and MQTT. The following command downloads and starts a single HiveMQ trial node.

    docker run -p 8080:8080 -p 1883:1883 hivemq/hivemq4

客户端(Python)

要在 Python 中使用 MQTT,你可以使用 Eclipse Paho MQTT 客户端库。以下是一个简单的示例,演示了如何在 Python 中创建一个 MQTT 客户端并连接到 MQTT 服务器、发布消息和订阅主题。

首先,你需要安装 Eclipse Paho MQTT 客户端库。你可以使用 pip 来安装:

pip install paho-mqtt

然后,以下是一个示例代码:

订阅者示例:
import paho.mqtt.client as mqtt
​
def on_subscribe(client, userdata, mid, reason_code_list, properties):
    # Since we subscribed only for a single channel, reason_code_list contains
    # a single entry
    if reason_code_list[0].is_failure:
        print(f"Broker rejected you subscription: {reason_code_list[0]}")
    else:
        print(f"Broker granted the following QoS: {reason_code_list[0].value}")
​
def on_unsubscribe(client, userdata, mid, reason_code_list, properties):
    # Be careful, the reason_code_list is only present in MQTTv5.
    # In MQTTv3 it will always be empty
    if len(reason_code_list) == 0 or not reason_code_list[0].is_failure:
        print("unsubscribe succeeded (if SUBACK is received in MQTTv3 it success)")
    else:
        print(f"Broker replied with failure: {reason_code_list[0]}")
    client.disconnect()
​
def on_message(client, userdata, message):
    # userdata is the structure we choose to provide, here it's a list()
    userdata.append(message.payload)
    # We only want to process 10 messages
    if len(userdata) >= 10:
        client.unsubscribe("$SYS/#")
    print("Received message '" + str(message.payload) + "' on topic '" + message.topic + "'")
​
def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print(f"Failed to connect: {reason_code}. loop_forever() will retry connection")
    else:
        # we should always subscribe from on_connect callback to be sure
        # our subscribed is persisted across reconnections.
        client.subscribe("$SYS/#")
​
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.on_subscribe = on_subscribe
mqttc.on_unsubscribe = on_unsubscribe
​
mqttc.user_data_set([])
mqttc.connect("mqtt.eclipseprojects.io")
mqttc.loop_forever()
print(f"Received the following message: {mqttc.user_data_get()}")
发布者示例:
import time
import paho.mqtt.client as mqtt
​
def on_publish(client, userdata, mid, reason_code, properties):
    # reason_code and properties will only be present in MQTTv5. It's always unset in MQTTv3
    try:
        userdata.remove(mid)
    except KeyError:
        print("on_publish() is called with a mid not present in unacked_publish")
        print("This is due to an unavoidable race-condition:")
        print("* publish() return the mid of the message sent.")
        print("* mid from publish() is added to unacked_publish by the main thread")
        print("* on_publish() is called by the loop_start thread")
        print("While unlikely (because on_publish() will be called after a network round-trip),")
        print(" this is a race-condition that COULD happen")
        print("")
        print("The best solution to avoid race-condition is using the msg_info from publish()")
        print("We could also try using a list of acknowledged mid rather than removing from pending list,")
        print("but remember that mid could be re-used !")
​
unacked_publish = set()
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
mqttc.on_publish = on_publish
​
mqttc.user_data_set(unacked_publish)
mqttc.connect("mqtt.eclipseprojects.io")
mqttc.loop_start()
​
# Our application produce some messages
msg_info = mqttc.publish("paho/test/topic", "my message", qos=1)
unacked_publish.add(msg_info.mid)
​
msg_info2 = mqttc.publish("paho/test/topic", "my message2", qos=1)
unacked_publish.add(msg_info2.mid)
​
# Wait for all message to be published
while len(unacked_publish):
    time.sleep(0.1)
​
# Due to race-condition described above, the following way to wait for all publish is safer
msg_info.wait_for_publish()
msg_info2.wait_for_publish()
​
mqttc.disconnect()
mqttc.loop_stop()

成功运行

Received message 'b'my message'' on topic 'paho/test/topic'
Received message 'b'my message2'' on topic 'paho/test/topic'

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

子龙烜

坦克大战系列,手把手带你实现

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

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

打赏作者

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

抵扣说明:

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

余额充值