MQTT 优势
- 轻量级
- MQTT 开销低、报文小,消耗更少的资源,即使在有限的能力下也能实现高效的通信。
- 可靠
- MQTT 支持多种
QoS
等级、会话感知和持久连接,即使在困难的条件下也能保证消息的可靠传递
- MQTT 支持多种
- 安全
- MQTT 提供传输层安全(TLS)和安全套接层(SSL)加密功能。此外,MQTT 还通过用户名/密码凭证或客户端证书提供身份验证和授权机制,以保护网络及其资源的访问。
- 双向通信
- MQTT 的发布-订阅模式为设备之间提供了无缝的双向通信方式。客户端既可以
向主题发布消息
,也可以订阅接收特定主题的消息
- MQTT 的发布-订阅模式为设备之间提供了无缝的双向通信方式。客户端既可以
- 连续、有状态的会话:
-
MQTT 提供了客户端与 Broker 之间保持有状态会话的能力,这使得系统即使在断开连接后也能记住订阅和未传递的消息。
-
客户端还可以在建立连接时指定一个保活间隔,这会促使 Broker 定期检查连接状态。如果连接中断,Broker 会储存未传递的消息(根据 QoS 级别确定),并在客户端重新连接时尝试传递它们。
-
MQTT术语
MQTT 客户端
任何运行 MQTT 客户端库的应用或设备都是 MQTT 客户端。例如,使用 MQTT 的即时通讯应用是客户端,使用 MQTT 上报数据的各种传感器也是客户端。
MQTT Broker(代理服务器)
MQTT Broker 负责处理客户端请求,包括建立连接、断开连接、订阅和取消订阅等操作,同时还负责消息的转发。
发布-订阅模式
发布者和订阅者之间无需建立直接连接,而是通过MQTT Broker
来负责消息的路由和分发。
Topic
消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)
下图展示了 MQTT 发布/订阅过程。温度传感器作为客户端连接到 MQTT Broker,并通过发布操作将温度数据发布到一个特定主题(例如 Temperature)。MQTT Broker 接收到该消息后会负责将其转发给订阅了相应主题(Temperature)的订阅者客户端。
MQTT消息
MQTT消息格式
MQTT消息由固定头部、可变头部和负载组成。固定头部包含消息的基本信息,如消息类型、服务质量(QoS)级别、保留标志等。
QoS
MQTT 提供了三种服务质量(QoS),在不同网络环境下保证消息的可靠性。
QoS 0
:消息最多传送一次。如果当前客户端未联网,它将丢失这条消息, 再次联网也收不到了。
QoS 1
:消息至少传送一次,确保消息到达, 但可能会发生重复。
QoS 2
:确保消息正好传送一次,避免消息重复或丢失。
MQTT协议通过交换预定义的MQTT消息来通信, MQTT定义了十四种不同类型的消息
MQTT消息类型
- CONNECT: 客户端请求连接服务端
- CONNACK: 连接报文确认
- PUBLISH: 发布消息
- PUBACK QoS1 消息发布收到确认
- PUBREC: 发布收到(保证交付第一步)
- PUBREL: 发布释放(保证交付第二步)
- PUBCOMP: QoS2 消息发布完成(保证交互第三步)
- SUBSCRIBE: 客户端订阅请求
- SUBACK: 订阅请求报文确认
- UNSUBSCRIBE: 客户端取消订阅请求
- UNSUBACK: 取消订阅报文确认
- PINGREQ: 客户端到服务端心跳请求
- PINGRESP: 服务端到客户端心跳响应
- DISCONNECT: 客户端断开连接
payload
消息的内容。
MQTT心跳机制
就像我们的心脏, MQTT客户端定期发送心跳包(PINGREQ),表明自己的存在和健康状况。服务端收到心跳请求后,会回复一条心跳响应(PINGRESP)
如果服务器在一定时间内没有接收到心跳包,就会认为客户端出现异常或离线。
MQTT遗嘱
客户端在「活着」的时候设置并发送遗嘱消息,以便在客户端意外断线时由服务端公布。
意外断线
指客户端在没有发送 DISCONNECT 报文的情况下失去了心跳信号,这通常发生在网络故障或下线等情况下。
此时,服务端会察觉到客户端的异常断开,并将客户端的遗嘱消息发布出来。然而,如果客户端正常断开连接并发送了 DISCONNECT 报文,遗嘱则不会启动,服务端也不会发布客户端的遗嘱消息。
MQTT的实现
为了更好地理解MQTT协议的实际应用,以下是一个简单的MQTT实现示例,包括客户端和服务器的代码。
python
代码解读
复制代码
import paho.mqtt.client as mqtt # 连接回调函数 def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe("test/topic") # 消息回调函数 def on_message(client, userdata, msg): print(f"{msg.topic} {msg.payload}") # 创建MQTT客户端 client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message # 连接MQTT服务器 client.connect("mqtt.eclipse.org", 1883, 60) # 开始循环,等待消息 client.loop_forever()
python
代码解读
复制代码
import paho.mqtt.client as mqtt # 创建MQTT客户端 client = mqtt.Client() # 连接MQTT服务器 client.connect("mqtt.eclipse.org", 1883, 60) # 发布消息到主题 client.publish("test/topic", "Hello MQTT") # 断开连接 client.disconnect()
在这个示例中,创建了一个MQTT客户端,并连接到公共MQTT服务器(mqtt.eclipse.org)。连接成功后,服务器订阅了主题test/topic,并在接收到消息时打印消息内容。客户端代码创建了另一个MQTT客户端,并连接到同一MQTT服务器,发布消息到主题test/topic,然后断开连接。