诞生:
MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道。目标是拥有一个带宽有效且使用很少电池电量的协议,因为这些设备是通过卫星链路连接的,当时这种设备非常昂贵。 与HTTP及其请求/响应范例相比,该协议使用发布/订阅体系结构。发布/订阅是事件驱动的,可以将消息推送到客户端。中央通信点是MQTT代理,它负责调度发送者和合法接收者之间的所有消息。向代理发布消息的每个客户端都在消息中包含一个主题。主题是代理的路由信息。每个想要接收消息的客户端都订阅某个主题,并且代理将具有匹配主题的所有消息传递给客户端。因此,客户不必彼此了解,他们只通过主题进行通信。该架构支持高度可扩展的解决方案,而不依赖于数据生产者和数据使用者。
发布订阅:
每个MQTT客户端都与代理具有永久打开的TCP连接,在有新内容的情况下,代理会将信息推送到客户端。如果此连接在任何情况下中断,MQTT代理可以缓冲所有消息,并在它重新联机时将它们发送到客户端。MQTT中用于分派消息的核心概念是主题。
topic 通配符:
+ 可以过滤一个层级, 代表任意一层
# 只能出现在主题最后,表示过滤任意级别的层级。
如:消息类型
/楼层/厕所/坑位
/楼层/厕所/温度
/5楼/+/温度 订阅所有厕所温度消息
/5楼/# 订阅5楼的所有消息(厕所的坑位和温度消息)
注: MQTT允许使用通配符订阅主题,但是并不允许使用通配符广播。
消息质量 QoS (可变报头与QoS有关系)
0 最多一次
1 最少一次
2 恰好一次
控制报文的结构
说明 | 字节 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
固 定 报 头 | 控 制 报 文 类 型 | 1 | MQTT控制报文的类型(16种) | 用于指定控制报文类型的标志位(和前面对应16种) 第3位: 控制报文重复分发 第2,1 位:控制消息质量,值 0 1 2 第0位: PUBLISH报文的保留标志,1保留 0 不保留 | ||||||
剩 余 长 度 | 2 | 表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。 剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节,且按照大端方式进行编码。因此每个字节可以编码128个数值和一个延续位(continuation bit)。 剩余长度字段最大4个字节,所有最长为 OXFF OXFF OXFF OX7F = 268435455 byte = 256M 。 最大就可以传输256M 控制报文。最后一位只能是OX7F ,因为:采用的是变长编码方案,如上所述。 | ||||||||
3 | ||||||||||
4 | ||||||||||
5 | ||||||||||
可变报头 | 6 | 就是消息标识位。 PUBLISH(QoS > 0时), PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE, SUBACK,UNSUBSCRIBE,UNSUBACK,有可变报头。 可变报头两个字节,非零16位报文标识符(释放后就可以再使用) 客户端和服务端相互独立分配报文标识符。可以并行发送消息 | ||||||||
7 | ||||||||||
有效负载 | ..... | 业务消息,如订阅的主题,需要登录的用户名密码等等 |
1、固定报头
1.1 控制报文类型
MQTT 使用一个字节的高4位定义 16种报文类型,其中两种是保留的。如下表:
名字 | 值 | 报文流动方向 | 描述 |
Reserved | 0 | 禁止 | 保留 |
CONNECT | 1 | 客户端到服务端 | 客户端请求连接服务端 |
CONNACK | 2 | 服务端到客户端 | 连接报文确认 |
PUBLISH | 3 | 两个方向都允许 | 发布消息 |
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 | 客户端到服务端 | 客户端断开连接 |
Reserved | 15 | 禁止 | 保留 |
控制报文标识位,使用固定报头的低4位包含每个MQTT控制报文类型特定的标志,见下表。
表格任何标记为“保留”的标志位,都是保留给以后使用的,必须设置为表格中列出的值。
如果收到非法的标志,接收者必须关闭网络连接。
行号 | 控制报文 | 固定报头标志 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
0 | CONNECT | Reserved | 0 | 0 | 0 | 0 |
1 | CONNACK | Reserved | 0 | 0 | 0 | 0 |
2 | PUBLISH | Used in MQTT 3.1.1 | DUP1 | QoS2 | QoS2 | RETAIN3 |
3 | PUBACK | Reserved | 0 | 0 | 0 | 0 |
4 | PUBREC | Reserved | 0 | 0 | 0 | 0 |
5 | PUBREL | Reserved | 0 | 0 | 1 | 0 |
6 | PUBCOMP | Reserved | 0 | 0 | 0 | 0 |
7 | SUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
8 | SUBACK | Reserved | 0 | 0 | 0 | 0 |
9 | UNSUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
10 | UNSUBACK | Reserved | 0 | 0 | 0 | 0 |
11 | PINGREQ | Reserved | 0 | 0 | 0 | 0 |
12 | PINGRESP | Reserved | 0 | 0 | 0 | 0 |
13 | DISCONNECT | Reserved | 0 | 0 | 0 | 0 |
- DUP1 =控制报文的重复分发标志
- QoS2 = PUBLISH报文的服务质量等级
- RETAIN3 = PUBLISH报文的保留标志
1.2 剩余长度
剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。
更大的值按下面的方式处理:低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节,且按照大端方式进行编码。因此每个字节可以编码128个数值和一个延续位(continuation bit)。(参考大端小端备注)
剩余长度字段最大4个字节。
能传输数据长度:
- 1个字节时,从0(0x00)到127(0x7f)
- 2个字节时,从128(0x80,0x01)到16383(0Xff,0x7f)
- 3个字节时,从16384(0x80,0x80,0x01)到2097151(0xFF,0xFF,0x7F)
- 4个字节时,从2097152(0x80,0x80,0x80,0x01)到268435455(0xFF,0xFF,0xFF,0x7F)=256M
2、可变报头
个人理解:就是消息标识位。
控制报文PUBLISH(QoS > 0时), PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE, SUBACK,UNSUBSCRIBE,UNSUBACK,有可变报头。
可变报头两个字节,非零16位报文标识符(释放后就可以再使用)
客户端和服务端相互独立分配报文标识符。可以并行发送消息
客户端每次发送一个新的这些类型的报文时都必须分配一个当前未使用的报文标识符 [MQTT-2.3.1-2]。
如果一个客户端要重发这个特殊的控制报文,在随后重发那个报文时,它必须使用相同的标识符。当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。
控制报文 | 报文标识符字段 |
CONNECT | 不需要 |
CONNACK | 不需要 |
PUBLISH | 需要(如果QoS > 0) |
PUBACK | 需要 |
PUBREC | 需要 |
PUBREL | 需要 |
PUBCOMP | 需要 |
SUBSCRIBE | 需要 |
SUBACK | 需要 |
UNSUBSCRIBE | 需要 |
UNSUBACK | 需要 |
PINGREQ | 不需要 |
PINGRESP | 不需要 |
DISCONNECT | 不需要 |
3、有效载荷 Payload
就是应用消息。下表列出了需要有效载荷的控制报文:
控制报文 | 有效载荷 | 备注 |
CONNECT | 需要 | 用户名密码,证书信息等 |
CONNACK | 不需要 | |
PUBLISH | 可选 | 业务数据 |
PUBACK | 不需要 | |
PUBREC | 不需要 | |
PUBREL | 不需要 | |
PUBCOMP | 不需要 | |
SUBSCRIBE | 需要 | 订阅消息的主题 |
SUBACK | 需要 | 确认成功的主题 |
UNSUBSCRIBE | 需要 | 取消订阅的主题 |
UNSUBACK | 不需要 | |
PINGREQ | 不需要 | |
PINGRESP | 不需要 | |
DISCONNECT | 不需要 |
上面的清楚了,具体的控制报文就很容易看明白。可以自行参考协议官网。
字节序参考:https://blog.youkuaiyun.com/convict_eva/article/details/90899991
参考:https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/01-Introduction.html