MQTT v 3.1 中⽂文版
Abstract/概览(MQTT V3.1)
MQ遥测传输(MQTT)是轻量级基于代理的发布/订阅的消息传输协议,设计思想是开放、简单、轻量、
易于实现。这些特点使它适用于受限环境。例如,但不仅限于此:
• 网络代价昂贵,带宽低、不可靠。
• 在嵌入设备中运行,处理器和内存资源有限。
该协议的特点有:
• 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
• 对负载内容屏蔽的消息传输。
• 使用TCP/IP提供网络连接。
• 有三种消息发布服务质量:
•
•
•
“至多一次”,消息发布完全依赖于底层TCP/IP网络。会发生消息丢失或重复。这一级别可用于如
下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
“至少一次”,确保消息到达,但消息重复可能会发生。
“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会
导致不正确的结果。
• 小型传输,开销很小(固定长度的头部是2字节),协议交换最小化,以降低网络流量。
• 使用LastWill和Testament特性通知有关各方客户端异常中断的机制。
1. Introduction/介绍(MQTT V3.1)
本规范被分成三个主要部分:
• 所有的数据包类型的消息格式
• 每个数据包类型的具体细节
• 数据包如何在服务器及客户端传输
附录里提供了如何使用主题通配符(topic wildcard)的信息
1.1 v3.0与v3.1的一些变化
以下是MQTT V3和MQTT V3.1之间的变化:
• 用户名及密码能在“CONNECT”包里一并发出
• 由于安全问题,“CONNACK”包里定义了新的返回码
• 未认证“PUBLIC”或“SUBSCRIBE”的命令不会通知客户端,即使该命令尚未执行完成MQTT流程
• MQTT现在支持完整的UTF-8字符集,而不是仅仅是US-ASCII subset。
“CONNECT”数据包里协议号仍保持不变,仍然为“3”,现有的MQTT V3服务器实现应能够接受来自客户端
的连接,支持本次修订,只要他们正确考虑了的“Remaining Length”字段,只是忽略了额外的安全信息。
1
MQTT v 3.1 中⽂文版
2. Message format/消息格式(MQTT
V3.1)
每个MQTT命令消息的消息头都包含一个固定的报头。一些消息也要求一个可变的报头和一个payload。
下面将描述消息头的格式:
2.1 Fixed header / 固定报头
2.2 Variable header / 可变报头
2.3 Payload
2.4 Message identifiers
2.5 MQTT and UTF-8
2.6 Unused bits
2.1 Fixed header/固定报头(MQTT
V3.1)
每个MQTT命令消息的消息头都包含一个固定的报头。下表显示了固定的报头格式。
Byte 1
包含消息类型和FLAGS((DUP,QoS级别,RETAIN)字段
Byte 2
(至少一个字节)包含的剩余长度字段。
这些字段会在以下各部分说明。所有数据值都是bigi-endian(大端)order:高字节在低字节之前。一个
16位字先是最高有效位(MSB),其次是最低有效位(LSB)
2
MQTT v 3.1 中⽂文版
消息类型
位置:byte 1,bits 7-4
无符号4位值,这个版本的枚举值如下表所示:
(0->保留;1->客户端请求连接到服务器;2->连接确认;3->发布消息;4->发布确认;5->发布收稿
(有保证的交付第1部分);6->出版发行(有保证交付第2部分);7->发布完整(有保证的交付第3部
分);8->客户端订阅请求;9->订阅确认;10->客户端退订请求;11->退订确认;12->ping请求;13-
>ping相应;14->客户端端口;15->保留;)
FLAGS
剩下的三位分别为DUP,QoS及RETAIN字段,bit位置如下表所示
3
MQTT v 3.1 中⽂文版
DUP
位置:byte 1,bit 4
这个标识是一个集合,当client或者server企图重
发“PUBLISH”、“PUBREL”、“SUBSCRIBE”、“UNSUBSCRIBE”消息时,这适用于信息的QoS值大于零
(0),并且消息确认是必需的。当设置的DUP位,可变头部包含一个消息ID。
接收者应视作为一个提示消息以此标识判断此消息以前是否收到。它不应该依赖于检测重复。
QoS
位置:byte 1,bits 2-1;
此标识指示发送消息的交付质量等级。QoS级别如下表所示:
RETAIN
位置:byte 1,bit 0
这个标识只用于“PUBLISH”消息。当客户端发送一个PUBLISH消息到服务器,如果保留标识位置(1),
当消息发送给当前用户服务器应该保留这条消息。
当一个新的订阅者订阅某一个主题,最后保留的某主题消息应被发送到用户并带着“RETAIN”标识位置。
如果没有保留消息,则不发送。
4
MQTT v 3.1 中⽂文版
这对于发布者发错消息时非常有用,它允许一个新的订阅者立即接收到最重要的数据。
当服务器发送给客户端一个PUBLISH,发现原始的PUBLISH已经存在时,Retain标识不应该被重置,忽略
掉原始PUBLISH的Retain标识。也就是说,允许客户端区分那些已经被接收的消息,正在接收的消息,以
及即时接收的消息。
保留的消息应该在服务器重启启动后也应该保留下来。
服务器可以删除某个已保留的消息,如果接收的消息长度为0或者保留标识为设置同一个主题。
Remaining Length
位置:byte 2
表示当前的消息剩余的字节数,包括数据在可变头和有效载荷。
可变长度编码方案采用了单字节的消息,多大127个字节长。较长的消息处理方式如下,每个字节7位编
码剩余长度的数据,和第八位表示在下面还有值。每个字节编码128个值和一个“延续位”。例如,数字64
十进制编码为一个字节的十进制64,十六进制0×40的。
321十进制(=65+2*128)编码为两个字节的重要的最初性最低。
第一个字节65+128=193.需要注意的是最高位表明至少有下列其中一个字节。第二个字节是2。
协议限制最多四个字节表示,这允许应用程序发送消息到268435455(256M)。
这个数字表示:值为0xFF,0xFF,0xFF,0x7F。
下表显示了增加字节数所代表的剩余长度值。
该算法编码成可变长度编码的十进制数(X方案如下)
do
digit = X MOD 128
X = X DIV 128
// if there are more digits to encode, set the top bit of this digit
if ( X > 0 )
digit = digit OR 0x80
endif
''output'' digit
while ( X> 0 )
MOD是模运算符(% in C),DIV是整数除法(/ in C),OR是逐位或(| in C)。剩余长度字段解码算
法如下:
5
MQTT v 3.1 中⽂文版
multiplier = 1
value = 0
do
digit = ''next digit from stream''
value += (digit AND 127) * multiplier
multiplier *= 128
while ((digit AND 128) != 0)
AND是操作符(& in C)
这种算法终止时,value包含以字节为单位的剩余长度。
剩余长度编码是不可变头的一部分。字节数用于编码的剩余长度,不利于剩余长度值。可变长度的“扩展
字节”是固定的头,而不是可变头的一部分。
2.2 variable header/可变的报头
(MQTT V3.1)
MQTT命令消息的某些类型还包括一个variable header组件。它位于fixed header和payload之间。
Remaining Length字段的可变长度不是variable header的一部分。Remaining Length字段的字节不是
Remaining Length值的字节计数。它的值只考虑variable header和playload。更多信息查看Fixed
header。
Variable header的格式在下面的章节描述,它们必须顺序出现在header里。
协议名称
这个协议名称代表可变头的一个MQTT CONNECT消息。该字段是UTF8编码的字符串,代表协议名称
MQlsdp,大写显示。
协议版本
协议版本代表可变头的CONNECT消息。
该字段是一个8位无符号值,描述由客服端所使用的协议的修订基本,当前版本的协议为3(0×03),如
下表所示。
6
MQTT v 3.1 中⽂文版
Connect flags(连接标志)
The Clean session, Will, Will QoS 和 Retain flags 在可变头的CONNECT消息里是存在的。
Clean session flag
Position:bit 1 of the Connect flags bytes(连接标志字节的第1位)
如果不设置(0),那么服务器必须存储客户端的订阅后断开。这包括继续存储订阅消息QoS1和QoS2消
息,以便当客户端重新连接时它们能传递。服务器还必须保持在连接丢失delivered in-flight消息的状态。
此信息必须保持,直到客户端重新连接。
如果设置(1),那么服务器必须放弃任何以前客户端维护的信息和让连接保持“clean”。当客户端断开连
接时,服务器还必须丢弃一切状态。
通常情况下,一个客户端将在一个模式下或者其他情况下操作,并且不会改变。该选择将取决于
application。一个clean的会话的客户端将不会接收到过时的信息,每次连接时它必须重新订阅。一个
non-clean会话的客户端不会错过任何QoS1或者QoS2的信息,当它失去连接时会被发布。当它们被发布
出去时QoS 0不会被存储。
这个标志以前被称为“Clean start”,它已经被重命名,它适用于整个会话,不仅仅是初始连接。
当这个客户端永远不会重新连接时,一个服务器可以为客户端提供一种清除存储信息的管理机制。
在当前版本的协议中这个字节的0位不使用。它是为将来使用保留。
Will flag
Position:bit 2 of the Connect flags byte(连接标志字节的第2位)
Will message定义了当服务器与客户端通信遇到I/O错误或客户端没有在一定时间计划内保持连接时,会
发布一个message。服务器从客户端接收到DISCONNECT消息时,并不会触发服务器发送一条Will
message。
如果设置Will flag,Will QoS和Will Retain字段必须存在于Connect flags字节中,Will Topic和Will message
字段必须在payload里。
Will flag的格式如下表所示:
7
MQTT v 3.1 中⽂文版
在当前版本的协议中这个字节的0位不使用。它是为将来使用保留。
Will QoS
Position:bits 4 and 3 of the Connect flags byte.(连接标志字节的第4位和3位。)
当一个连接中的客户端被偶然的断开时为一个Will message定义在Will QoS字段中的QoS级别。Will
message被定义在CONNECT message的payload中。(A connecting client specifies the QoS level in the
Will QoS field for a Will message that is sent in the event that the client is disconnected involuntarily.
The Will message is defined in the payload of a CONNECT message.)
如果设置Will flag,Will QoS字段是强制性的,否则他的值将被忽略。
Will QoS的值是0(0×00),1(0×01),or 2(0×02)。Will QoS标志显示在下面的表格中。
在当前版本的协议中这个字节的0位不使用。它是为将来使用保留的。
Will Retain flag
Position:bit 5 of the connect flags byte(连接标志字节的第5位)
当客户端意外的断开连接时,Will Retain标志说明服务器是否应该保留被服务器发布的Will message。
如果设置Will Retain标志,Will Retain标志是强制性的,否则它将被忽略。Will Retain标志的格式如下表
所示。
在当前版本的协议中这个字节的0位不适用。它是为将来使用保留。
8