四、MQTT数据结构分析
CONNECT报文的固定报头
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
说明 |
byte 0 |
MQTT报文类型(0x01) |
Reserved |
|
||||||
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
|
|
byte 1 |
Msg Len: 消息长度字段 ,长度不定 |
|
|||||||
byte L+1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
长度 MSB(0) |
byte L+2 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
长度 LSB (4) |
byte L+3 |
0x4D |
‘M’ |
|||||||
byte L+4 |
0x51 |
‘Q’ |
|||||||
byte L+5 |
0x54 |
‘T’ |
|||||||
byte L+6 |
0x54 |
‘T’ |
|||||||
byte L+7 |
0x04 – 协议级别 |
Level(4) |
|||||||
byte L+8 |
User Name Flag |
Password Flag |
Will Retain |
Will Qos |
Will Flag |
Clearn Session |
Reserved |
|
|
x |
x |
x |
x |
x |
x |
x |
x |
|
|
byte L+9 |
保持连接 Keep Alive MSB |
|
|||||||
byteL+10 |
保持连接 Keep Alive LSB |
|
|||||||
以下为Payload,每个字段长度不一 |
|||||||||
Client Identifier – 该字段可有可无,如果客户端提供了一个零字节的客户端标识符,它必须将清理会话标志设置为1 |
|||||||||
|
Client Identifier Length MSB |
|
|||||||
|
Client Identifier Length LSB |
|
|||||||
|
Client Identifier Data -- UFT-8 String |
|
|||||||
遗嘱主题 Will Topic – 当Will Flag = 1才有该字段 |
|||||||||
遗嘱消息 Will Message – 当Will Flag = 1才有该字段 |
|||||||||
User Name – 用户名,例如:admin,该字段只有当User Name Flag = 1才有效 |
|||||||||
|
User Name Length MSB |
|
|||||||
|
User Name Length LSB |
|
|||||||
|
User Name Data |
|
|||||||
Password – 密码,例如:password,该字段只有当Password Flag = 1才有效 |
|||||||||
|
Password Length MSB |
|
|||||||
|
Password Length LSB |
|
|||||||
|
Password Data |
|
CONNACK – 确认连接请求
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
说明 |
byte 0 |
MQTT报文类型(0x02) |
Reserved |
|
||||||
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
|
|
byte 1 |
可边长的长度字段 = 2 |
|
|||||||
byte 3 |
Reserved 保留位 |
SP |
连接确认标志 |
||||||
byte 4 |
0x00 – 链接已经被服务器接受了 |
连接返回码 |
|||||||
0x01 – 服务器不支持的客户端指定的版本 |
|||||||||
0x02 - 连接已拒绝,不合格的客户端标识符 |
|||||||||
0x03 - 连接已拒绝,服务端不可用 |
|||||||||
0x04 - 连接已拒绝,无效的用户名或密码 |
|||||||||
0x06~0xFF – 保留 |
PUBLISH – 发布消息
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x03) |
DUP |
QoS-H |
QoS-L |
RETAIN |
QoS-质量等级 |
|||
0 |
0 |
1 |
1 |
x |
x |
x |
x |
||
|
可边长的长度字段 = L |
|
|||||||
主题名 Topic Name |
|||||||||
|
Topic Name MSB |
|
|||||||
|
Topic Name LSB |
|
|||||||
|
Topic Name Data |
|
|||||||
报文标识符 Packet Identifier – 当QoS != 0 时才会有该字段 |
|||||||||
|
MSB |
|
|||||||
|
LSB |
|
|||||||
Payload |
RETAIN:
如果被设置为1:
1、 服务器必须要保存这个发布的主题的信息和服务质量
2、 如果一个别的客户端请求一个新的订阅时存在保留的信息,服务器必须要将信息发给这个订阅者
3、 如果发布的主题服务等级为0,那么必须丢弃之前已存在的同名主题,即使这个主题还未发布完成
如果被设置成0:
服务器不能保存这个发布的主题的信息和服务质量,如果当前存在同名主题也不能丢弃已存在同名主题的信息
消息发布的回复:(Cline)
1、 QoS=0: 没有回复
2、 QoS=1: PUBACK
3、 QoS=2: PUBREC + PUBREL + PUBCOMP
PUBACK –发布确认(QoS=1)
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x04) |
Reserved |
PUBACK |
||||||
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 2 |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与发布的标识符一致 |
|||||||
|
LSB |
其工作流程如下:
Publish Source PUBLISH 0x03 Publish Recptora
------------------------------------------------->
PUBREC 0x04
<-------------------------------------------------
QoS=2的发布反馈(PUBREC + PUBREL + PUBCOMP)
1.PUBREC:发布收到
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x05) |
Reserved |
PUBREC |
||||||
0 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 2 |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与发布的标识符一致 |
|||||||
|
LSB |
2.PUBREL:发布释放
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x06) |
Reserved |
PUBREL |
||||||
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 2 |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与发布的标识符一致 |
|||||||
|
LSB |
3.PUBCOMP:发布完成
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x07) |
Reserved |
PUBCOMP |
||||||
0 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 2 |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与发布的标识符一致 |
|||||||
|
LSB |
其工作流程如下:
Publish Source PUBLISH 0x03 Publish Recptora
------------------------------------------------------------>
PUBREC 0x05
<-----------------------------------------------------------
PUBREL 0x06
----------------------------------------------------------->
PUBCOMP 0x07
<-----------------------------------------------------------
SUBSCRIBE - 订阅主题
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
说明 |
|
byte 0 |
MQTT报文类型(0x08) |
Reserved |
|
|||||||
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
|
||
byte 1 |
可边长的长度字段 = L |
|
||||||||
报文标识符 Packet Identifier |
||||||||||
|
MSB |
|
||||||||
|
LSB |
|||||||||
主题过滤器_1 |
||||||||||
|
长度 MSB |
|
||||||||
|
长度 LSB |
|
||||||||
|
Byte 1 |
|
||||||||
|
Byte 2 |
|
||||||||
|
…… |
|
||||||||
|
Byte N |
|
||||||||
|
Reserved |
主题服务质量等级 |
|
|||||||
|
X |
X |
||||||||
主题过滤器_2 |
||||||||||
|
长度 MSB |
|
||||||||
|
长度 LSB |
|
||||||||
|
Byte 1 |
|
||||||||
|
Byte 2 |
|
||||||||
|
…… |
|
||||||||
|
Byte N |
|
||||||||
|
Reserved |
主题服务质量等级 |
|
|||||||
|
X |
X |
||||||||
………… |
||||||||||
主题过滤器_N |
||||||||||
|
长度 MSB |
|
||||||||
|
长度 LSB |
|
||||||||
|
Byte 1 |
|
||||||||
|
Byte 2 |
|
||||||||
|
…… |
|
||||||||
|
Byte N |
|
||||||||
|
Reserved |
主题服务质量等级 |
|
|||||||
|
X |
X |
||||||||
SUBACK – 订阅确认
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
说明 |
byte 0 |
MQTT报文类型(0x09) |
Reserved |
|
||||||
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
|
|
byte 1 |
可边长的长度字段 = L |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与SUBSCRIBE一致 |
|||||||
|
LSB |
||||||||
订阅的返回结果列表 |
|||||||||
|
主题过滤器1订阅结果 |
|
|||||||
|
主题过滤器2订阅结果 |
|
|||||||
|
主题过滤器3订阅结果 |
|
|||||||
|
……… |
|
|||||||
|
主题过滤器3订阅结果 |
|
订阅结果:
0x00 - 最大QoS 0
0x01 - 成功 – 最大QoS 1
0x02 - 成功 – 最大 QoS 2
0x80 - Failure 失败
0x00, 0x01, 0x02, 0x80之外的SUBACK返回码是保留的,不能使用
UNSUBSCRIBE –取消订阅
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
说明 |
byte 0 |
MQTT报文类型(0x0A) |
Reserved |
|
||||||
1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
|
|
byte 1 |
可边长的长度字段 = L |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
|
|||||||
|
LSB |
||||||||
要取消订阅的主题过滤器_1 |
|||||||||
|
长度 MSB |
|
|||||||
|
长度 LSB |
|
|||||||
|
Byte 1 |
|
|||||||
|
Byte 2 |
|
|||||||
|
…… |
|
|||||||
|
Byte N |
|
|||||||
要取消订阅的主题过滤器_2 |
|||||||||
|
长度 MSB |
|
|||||||
|
长度 LSB |
|
|||||||
|
Byte 1 |
|
|||||||
|
Byte 2 |
|
|||||||
|
…… |
|
|||||||
|
Byte N |
|
|||||||
………… |
|||||||||
要取消订阅的主题过滤器_N |
|||||||||
|
长度 MSB |
|
|||||||
|
长度 LSB |
|
|||||||
|
Byte 1 |
|
|||||||
|
Byte 2 |
|
|||||||
|
…… |
|
|||||||
|
Byte N |
|
UNSUBACK – 取消订阅确认
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x0B) |
Reserved |
UNSUBACK |
||||||
1 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 2 |
|
|||||||
报文标识符 Packet Identifier |
|||||||||
|
MSB |
与UNSUBSCRIBE发出的一致 |
|||||||
|
LSB |
PINGREQ – 心跳请求
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x0C) |
Reserved |
PINGREQ |
||||||
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 0 |
|
PINGRESP – 心跳响应
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x0D) |
Reserved |
PINGRESP |
||||||
1 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 0 |
|
DISCONNECT – 断开连接
Offset |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
描述 |
|
MQTT报文类型(0x0E) |
Reserved |
DISCONNECT |
||||||
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
||
|
可边长的长度字段 = 0 |
|
主题名和主题过滤器 Topic Names and Topic Filters
主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层级 topic level 。
订阅的主题过滤器可以包含特殊的通配符,允许你一次订阅多个主题。
主题过滤器中可以使用通配符,但是主题名不能使用通配符,即订阅时可以用通配符一次订阅多个主题,但是发布主题时仅能发布一个主题,不能用通配符的形式发布多个主题。
通配符有以下两种:
’#’ -- 多层通配符,例如,如果客户端订阅主题 “sport/tennis/player1/#”,它会收到使用下列主题名发布的消息:
“sport/tennis/player1”
“sport/tennis/player1/ranking”
“sport/tennis/player1/score/wimbledon”
‘+’ – 单层通配符,例如, 如果客户端订阅主题“sport/tennis/+”,它会收到使用下列主题名发布的消息:
“sport/tennis/player1”
“sport/tennis/player2”
但是不会收到 “sport/tennis/player1/ranking” 。
同时,由于单层通配符只能匹配一个层级, “sport/+” 不匹配 “sport” 但是却匹配 “sport/”。