物联网通讯协议——MQTT协议

什么是MQTT协议?

MQTT协议是构建与tcp/ip协议的一种应用层协议,我们常见的http就是一种应用层协议。MQTT协议的优点在于可以使用极少的代码和有限的带宽去传输信息,因为其低开销,低带宽占用的及时通讯特点使其在物联网,小型设备直接的通讯等中十分常见。

MQTT协议的格式

每条MQTT的消息都包含一个固定的报头,有些消息会携带一个可变报文头和一个负荷。

固定头

固定头顾名思义就是每个mqtt消息头部都要包含的头部,它最少可为两字节。

字节 7 6 5 4 3 2 1 0
字节1 讯息类型 DUP标志 QoS等级 保留
字节2 剩余长度

上表为我们展示了固定头的格式。

字节一:

讯息类型占了第一个字节中的第7位到第4位,

助记符 枚举 描述
Reserved 0 已预留
CONNECT 1 客户端请求连接到服务器
CONNACK 2 连接确认
PUBLISH 3 发布讯息
PUBACK 4 发布确认
PUBREC 5 发布收到(保证交付部分1)
PUBREL 6 发布版本(保证交付的第2部分)
PUBCOMP 7 发布完成(保证交付的第3部分)
SUBSCRIBE 8 客户订阅请求
SUBACK 9 订阅确认
UNSUBSCRIBE 10 客户退订请求
UNSUBACK 11 退订确认
PINGREQ 12 PING请求
PINGRESP 13 PING回应
DISCONNECT 14 客户端正在断开连接
Reserved 15 已预留

DUP标志占字节一中的第3位,

当客户端或服务器尝试重新传递PUBLISH,PUBREL, SUBSCRIBE或UNSUBSCRIBE消息时,将设置此标志。这适用于QoS值大于零(0)且需要确认的消息。当DUP位置1时,变量头包括消息ID。

接收者应将此标志视为有关消息是否先前已被接收的提示。不应依靠它来检测重复项。

QoS等级占了第2到第1位,它表示了此PUBLISH消息传递的服务质量。

QoS 价值 第二位 第一位 描述
0 0 0 最多一次 Fire and Forget(发送完后就不管了,不用管目标有没有收到) <=1
1 0 1 最少一次 Acknowledged delivery(接收端一定要确认收到信息,没收到就继续发,发到目标收到为止) >=1
2 1 0 只能一次 Assured delivery(不惜一切代价把信息一次性地交付给目标) =1
3 1 1 保留

保留位于第0位,

如果用户在发送给服务端的信息中将该位置“1”,服务器就会保留发给给客户端的信息。

字节二:

此字节表示当前消息中剩余的字节数,包括变量头和有效载荷中的数据。

一个字节可最多表示127个字节的消息,这里可能就有人问了一个字节最大是1111 1111按道理来说应该是256才对啊?因为mqtt协议最多可以以4字节的形式来表示剩余消息中的字节数,所以每个字节的第8位数字表示是否需要再使用一个字节来表示剩下消息中的字节数,如果在第8位置“1”就表示再使用一个字节,置“0”就表示不调用。

可变头

下表显示了变量头的格式示例:

Description 7 6 5 4 3 2 1 0
Protocol Name
byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
byte 2 Length LSB (6) 0 0 0 0 0 1 1 0
byte 3 ‘M’ 0 1 0 0 1 1 0 1
byte 4 ‘Q’ 0 1 0 1 0 0 0 1
byte 5 ‘I’ 0 1 0 0 1 0 0 1
byte 6 ‘s’ 0 1 1 1 0 0 1 1
byte 7 ‘d’ 0 1 1 0 0 1 0 0
byte 8 ‘p’ 0 1 1 1 0 0 0 0
Protocol Version Number
byte 9 Version (3) 0 0 0 0 0 0 1 1
Connect Flags
byte 10 User name flag (1)
Password flag (1)
Will RETAIN (0)
Will QoS (01)
Will flag (1)
Clean Session (1)
1 1 0 0 1 1 1 x
Keep Alive timer
byte 11 Keep Alive MSB (0) 0 0 0 0 0 0 0 0
byte 12 Keep Alive LSB (10) 0 0 0 0 1 0 1 0

协议名称(Protocol Name)

协议名称位于MQTT CONNECT消息的变量标头中 。此字段是UTF编码的字符串。

协议版本(Protocol Version Number)

该字段是一个8位无符号值,表示客户端使用的协议的修订级别。

连接标志(Connect Flags)

Clean session,Will,Will QoS和保留标志存在于CONNECT消息的变量标头中。

清理会话标志(Clean Session)

位置:连接标志字节的位1。

如果设置为(0),则服务器必须在断开连接后存储客户端的订阅。这包括继续存储已订阅主题的QoS 1和QoS 2消息,以便在客户端重新连接时可以传递它们。服务器还必须在连接断开时保持正在传送的运行中消息的状态。在客户端重新连接之前,必须保留此信息。

如果设置为(1),则服务器必须丢弃有关客户端的任何先前维护的信息,并将连接视为“干净”。当客户端断开连接时,服务器还必须放弃任何状态。

预设置标志(Will flag)

位置:连接标志字节的位2。

Will消息定义当服务器在与客户端通信期间遇到I / O错误,或者客户端无法在Keep Alive计时器计划内进行通信时,服务器将代表客户端发布消息。服务器从客户端接收到DISCONNECT消息后,不会触发发送Will消息的操作。

如果设置了Will标志,则Will QoS和Will Retain字段必须出现在Connect标志字节中,而Will Topic和Will Message字段必须出现在有效负载中。

QoS

位置:连接标志字节的第4位和第3位。

如果客户端非自愿断开连接,则连接的客户端在Will消息的Will QoS字段中指定QoS级别。Will消息在CONNECT消息的有效负载中定义。

如果设置了Will标志,则Will QoS字段为必填字段,否则其值将被忽略。

Will QoS的值为0(0x00),1(0x01)或2(0x02)。下表显示了Will QoS标志。

将保留标志(will retain)

位置:连接标志字节的第5位。

Will Retain标志表示客户端是否意外断开连接时,服务器是否应保留由服务器代表客户端发布的Will消息。

如果设置了Will标志,则Will Retain标志是必需的,否则将被忽略。

用户名和密码标志(username and password flag)

位置:连接标志字节的第6位和第7位。

连接客户端可以指定用户名和密码,并且设置标志位表示CONNECT消息的有效负载中包括用户名和可选的密码。

如果设置了“用户名”标志,则“用户名”字段是必填字段,否则将忽略其值。如果设置了密码标志,则密码字段是必填字段,否则其值将被忽略。在不提供用户名的情况下提供密码是无效的。

保持活动计时器(Keep Alive timer)

保持活动计时器(以秒为单位)定义了从客户端收到的消息之间的最大时间间隔。它使服务器能够检测到与客户端的网络连接已断开,而不必等待长时间的TCP / IP超时。客户有责任在每个“保持活动”时间段内发送消息。在此时间段内没有数据相关消息的情况下,客户端会发送PINGREQ消息,服务器会通过PINGRESP消息进行确认 。

保持活动计时器可以通过MSB和LSB的顺序进行设置,它们分别占有2个字节。

负荷

以下类型的MQTT命令消息具有有效负载:

连接

有效负载包含一个或多个UTF-8编码的字符串。他们为客户端指定了一个无歧义的标识符,一个Will主题和消息以及要使用的用户名和密码。除了第一个以外的所有都是可选的,它们的存在是根据变量头中的标志确定的。

订阅

有效负载包含客户端可以订阅的主题名称和QoS级别的列表。这些字符串是UTF编码的。

后退

有效负载包含已授权QoS级别的列表。这些是服务器管理员已允许客户端订阅特定主题名称的QoS级别。授予的QoS级别以与相应的SUBSCRIBE消息中的主题名称相同的顺序列出。

学累了?听首歌吧!