TCP/IP协议—MQTT
- MQTT协议
- MQTT协议特点
- MQTT通信流程
- MQTT协议概念
- MQTT报文
- 固定报头
- 可变报头
- 有效载荷
MQTT协议
消息队列遥测传输(Message Queuing Telemetry Transport,MQTT)是一个基于客户端-服务器的消息发布/订阅传输协议。它的设计思想是轻巧、开放、简单、规范,因此易于实现。这些特点使得它对很多场景来说都是很好的选择,包括受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。
MQTT基于TCP协议(1883端口),同时支持TLS协议加密(8883端口)以及WebSocket协议。
MQTT协议源文档
MQTT协议特点
- 开放消息协议,简单易实现
- 发布订阅模式,一对多消息发布
- 基于TCP/IP网络连接,提供有序,无损,双向连接。
- 消息QoS支持,可靠传输保证
MQTT通信流程
客户端
使用MQTT的程序或设备。根据功能的不同也可称为发布者或者订阅者
- 打开连接到服务端的网络连接
- 发布应用消息给其它相关的客户端
- 订阅以请求接受相关的应用消息
- 取消订阅以移除接受应用消息的请求
- 关闭连接到服务端的网络连接
服务端
作为发送消息的客户端和请求订阅的客户端之间的中介。也被称为MQTT代理,因为服务器只做消息管理,不处理应用数据,而是转发应用数据。
- 接受来自客户端的网络连接
- 接受客户端发布的应用消息
- 处理客户端的订阅和取消订阅请求
- 转发应用消息给符合条件的已订阅客户端
- 关闭来自客户端的网络连接
MQTT协议概念
- 会话(Subscription):客户端和服务端之间的状态交互。每一个与服务端交互的客户端都会有一个client ID,这个ID是唯一ID,如果与其他的客户端重复,将会被服务器踢下线。
- 主题(topic):主题是应用消息的标签,发布以及订阅都是通过主题进行的。主题支持通配符,可以通过通配符实现同时向多个主题发布数据。
- 订阅(Subscription):通过订阅主题,接受服务器的数据。可以理解为微信订阅公众号。
- 发布(Public):通过主题讲信息发送到服务器。可以理解为微信公众号发推文。
- 服务质量(QoS):服务质量是MQTT控制数据可靠性的一个特性。QoS有三个等级,当双方的QoS等级不一致时,以等级低的一方为准。
- QoS 0:“最多一次”,尽操作环境所能提供的最大努力分发消息。只发送一次,数据可能会丢失或者因重发导致重复。
- QoS 1:“至少一次”,保证消息可以到达,但是可能会重复。发送多次,当服务器回复后停止发送,可能会因网络延迟导致对端收到多次。
- QoS 2:“仅一次”,保证消息只到达一次。确保只收到一次,分4步进行确认。
1. 发布者发送消息到服务器: 发布者将消息发送到MQTT服务器。
2. 服务器发送确认消息给发布者: 服务器收到消息后发送确认消息给发布者,告知消息已经收到。
3. 服务器将消息发送给订阅者: 服务器将消息发送给所有订阅者。
4. 订阅者发送确认消息给服务器: 订阅者收到消息后发送确认消息给服务器,告知消息已经收到。
- 遗嘱消息(Will Message):在网络连接非正常关闭的情况下,由服务端发布的应用消息。
- 消息保留(Retained Messages):发布者可以选择保留消息,这意味着 MQTT 服务器将保留最新的消息,并在订阅者订阅该主题时立即发送给它们。这对于传递状态信息或配置信息很有用。
MQTT报文
MQTT报文包含3部分
- 固定报头(Fixed Header):所有控制报文都包含,表示数据包类型及数据包的分组标识。
- 可变报头(Variable Header):部分控制报文包含,数据包类型决定可变报头是否存在。
- 有效载荷(Payload):部分控制报文包含,数据包类型决定可变报头是否存在。
固定报头
固定报头包含3部分
- MQTT报文类型(MQTT Control Packet type)
- MQTT报文类型标志位(Flags specific to each MQTT Control Packet type)
- 剩余长度(Remaining Length)
MQTT报文类型可以参考👇表格
类型 | 值 | 方向 | 描述 | 有效载荷 | 可变报头报文标识符 |
---|---|---|---|---|---|
Reserved | 0 | 禁止 | 保留 | 不需要 | 不需要 |
CONNECT | 1 | 客户端到服务端 | 客户端请求连接服务端 | 需要 | 不需要 |
CONNACK | 2 | 服务端到客户端 | 连接报文确认 | 不需要 | 不需要 |
PUBLISH | 3 | 两个方向都允许 | 发布消息 | 可选 | 需要(如果QoS>0) |
PUBACK | 4 | 两个方向都允许 | QoS 1消息发布收到确认 | 不需要 | 需要 |
PUBREC | 5 | 两个方向都允许 | 发布收到(保证交付第一步) | 不需要 | 需要 |
PUBREL | 6 | 两个方向都允许 | 发布释放(保证交付第二步) | 不需要 | 需要 |
PUBCOMP | 7 | 两个方向都允许 | QoS 2消息发布完成(保证交互第三步) | 不需要 | 需要 |
SUBSCRIBE | 8 | 客户端到服务端 | 客户端订阅请求 | 需要 | 需要 |
SUBACK | 9 | 服务端到客户端 | 订阅请求报文确认 | 需要 | 需要 |
UNSUBSCRIBE | 10 | 客户端到服务端 | 客户端取消订阅请求 | 需要 | 需要 |
UNSUBACK | 11 | 服务端到客户端 | 取消订阅报文确认 | 需要 | 需要 |
PINGREQ | 12 | 客户端到服务端 | 心跳请求 | 不需要 | 不需要 |
PINGRESP | 13 | 服务端到客户端 | 心跳响应 | 不需要 | 不需要 |
DISCONNECT | 14 | 两个方向都允许 | 断开连接通知 | 不需要 | 不需要 |
AUTH | 15 | 两个方向都允许 | 认证信息交换 | 不需要 | 不需要 |
MQTT报文类型标志位目前是保留位,当前只有MQTT 5.0 规范中PUBLISH用到。
- Bit 3:DUP,表示当前 PUBLISH 报文是否是一个重传的报文。
- Bit 2,1:QoS,表示当前 PUBLISH 报文使用的服务质量等级。
- Bit 0:Retain,表示当前 PUBLISH 报文是否是一个保留消息。
剩余长度
固定头的第二字节用来保存变长头部和消息体的总大小的,但不是直接保存的。这一字节是可以扩展,其保存机制,前7位用于保存长度,后一部用做标识。当最后一位为 1时,表示长度不足,需要使用二个字节继续保存。
可变报头
某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和有效载荷之间。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。
由于可变报头的内容根据报文类型的不同而不同,篇幅过长,具体可以参考👆MQTT协议源文档。
有效载荷
有效载荷是实现某种报文类型的核心,但是MQTT只有几种报文需要有效载荷。
- CONNECT:包含客户端的ClientID、订阅的Topic、Message以及用户名和密码。
- PUBLISH:包含客户端要发布的内容,当内容为空时则不存在。
- SUBSCRIBE:包含一系列的要订阅的主题以及QoS。
- SUBACK:包含服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
- UNSUBSCRIBE:包含客户端要订阅的主题。
- UNSUBACK:包含务器对于UNSUBSCRIBE所申请的主题及QoS进行确认和回复。
学习笔记,有问题欢迎指出
参考链接
https://mqtt.p2hp.com/