MQTT协议简析
定义
MQTT(Message Queuing Telemetry Transport,消息队列遥感传输)是一种基于publish/subscribe(发布/订阅)模式的轻量级通信协议,它构建在TCP/IP的协议上,有IBM于1999年发布
特性
- 低开销、低带宽提供实时可靠的消息服务
- 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合
- 对负载内容屏蔽的消息传输
- 使用TCP/IP提供网络连接(也有一些基于UDP叫做MQTT-SN)
应用场景
- 智能家居
- 物联网(IOT)
- 机器与机器(M2M)
- 偶尔拨号的医疗设备
- 卫星链路通信传感器
协议
MQTT的协议格式如下图所示:

固定头(Fixed header)
存在于所有的MQTT数据包中,表示数据包的类型及数据包的分组类标识,其格式如下图所示:

数据包类型
位置:第1个字节中的4-7位,占4位,是一个4位无符号值,数据包类型的类型、取值及说明如下图所示:

标识位
位置:第1个字节中的0-3位,占4位。每种数据包类型的标识位的取值是不一样的,也可能不使用标识位,在不使用标识位的消息类型中,标识位被作为保留位。如果收到无效的标志时,接收端必须关闭连接,每种数据包类型的标识位说明如下图所示:
- DUP:发布消息的副本。用来保证消息的可靠传输,如果设置为1,则在下面的变长中添加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。
- QOS:发布消息的质量,即保证消息传递的次数,取值有:
- 00:最多一次,即发送消息<=1次,存在不发送的情况
- 01:至少一次,即发送消息>=1次,存在同一消息发送多次的情况
- 10:一次,即消息保证会发送且只发送一次
- 11:预留
- RETAIN:发布保留标识位,表示服务器要保留本次推送的消息,如果有新的订阅者出现,就把这条消息推送给它
剩余长度(Retaining Length)
位置:第2个字节起,最大占4个字节
固定头的第2个字节起用来保存变长头部和消息体的总大小。这一字节是可以扩展的,其机制是:第7位用于保存长度,剩下一位用作是否需要更多字节来表示剩余长度。如果剩下一位是1,表示长度不足,需要使用第3个字节继续保存;如果最后一位是0,表示长度已足够,依次类推直到占满4个字节
可变头(Variable header)
MQTT某些类型的数据包中包含一个可变头,它位于固定头和消息体之间。可变头的内容因数据包类型不同而不同,很多类型数据包中都包含一个2字节的数据包标识符(可以理解为消息Message ID),这些类型的包有:PUBLISH(Qos>0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK,下图是需要报文标识符的类型:

消息体(Paload)
消息体(Paload)位于MQTT数据包的第3部分,在可变头的后面,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:
- CONNECT:消息体内容主要是:客户端的ClientID、订阅的主题Topic、消息Message、用户名、密码
- SUBSCRIBE:消息体内容是一系列的要订阅的主题及Qos
- SUBACK:消息体内容是服务器对于SUBSCRIBE所申请的主题及Qos进行确认和回复
- UNSUBSCRIBE:消息体内容是要取消订阅的主题
MQTT控制报文
CONNECT
可变头
下图是CONNECT的可变头:

Paload
CONNECT没有消息体
CONNACK
可变头
下图是CONNACK的可变头:

- 连接确认标志
第1个字节是 连接确认标志,位7-1是保留位且必须设置为0。 第0 (SP)位 是当前会话(Session Present)标志。 - 连接返回码
位置:可变报头的第2个字节。
值 | 返回码响应 | 描述 |
---|---|---|
0 | 0x00连接已接受 | 连接已被服务端接受 |
1 | 0x01连接已拒绝,不支持的协议版本 | 服务端不支持客户端请求的MQTT协议级别 |
2 | 0x02连接已拒绝,不合格的客户端标识符 | 客户端标识符是正确的UTF-8编码,但服务端不允许使用 |
3 | 0x03连接已拒绝,服务端不可用 | 网络连接已建立,但MQTT服务不可用 |
4 | 0x04连接已拒绝,无效的用户名或密码 | 用户名或密码的数据格式无效 |
5 | 0x05连接已拒绝,未授权 | 客户端未被授权连接到此服务器 |
6-255 | 保留 |
Paload
CONNACK无消息体
PUBLISH
可变头
下图是PUBLISH的可变头:

Paload
Publish的消息体要依据具体的业务进行填充
PUBACK
可变头
下图是PUBACK可变头:

Paload
PUBACK无消息体
SUBSCRIBE
可变头
SUBSCRIBE的可变头如下图所示:

Paload
SUBSUCRIBE的消息体如下图所示:
