1、MQTT V31协议规范中文版作者:International Business Machines Corporation (IBM)Eurotech翻译:明歌协议原文:摘要MQ遥测传输(MQ Telemetry Transport,MQTT)是一个轻量级的基于代理的发布/订阅式消息传输协议,它的设计目标是开放、简单、轻量和易于实现。这些特征使它适用于各种受限环境,比如,但不限于:网络代价昂贵,低带宽或不可靠。在嵌入设备中运行,处理器和内存资源有限。该协议的特性包括:使用发布/订阅消息模式,提供一对多的消息分发,解除应用程序耦合。消息传输对有效载荷内容不可知。使用TCP/IP提供基础网络连接。
2、有3个消息发布服务质量级别:“至多一次”,消息发布完全依赖于底层TCP/IP网络。消息有可能丢失或重复。这一级别可应用于如下情景,如环境传感器数据,丢失一次读记录无所谓,因为很快下一次读记录就会产生。“至少一次”,确保消息到达,但消息重复有可能发生。“只有一次”,确保消息到达且只到达一次。这一级别可用于如计费系统等场景,在计费系统中,消息丢失或重复可能会导致生成错误的费用。轻量传输,开销很小(固定头部的长度只有2字节),协议交换最小化,以降低网络流量。提供一种机制,当客户端异常中断时,利用 Last Will 和 Testament 特性来通知有关各方。版权声明 1999-2010 Eurot
3、ech, International Business Machines Corporation (IBM). All rights reserved.Permission to copy and display the MQ Telemetry Transport specification (the Specification), in any medium without fee or royalty is hereby granted by Eurotech and International Business Machines Corporation (IBM) (collectiv
4、ely, the Authors), provided that you include the following on ALL copies of the Specification, or portions thereof, that you make:A link or URL to the Specification at one of the Authors websites. The copyright notice as shown in the Specification. The Authors each agree to grant you a royalty-free
5、license, under reasonable, non-discriminatory terms and conditions to their respective patents that they deem necessary to implement the Specification. THE SPECIFICATION IS PROVIDED AS IS, AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRA
6、NTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. THE AUTHORS WIL
7、L NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THE SPECIFICATION.The name and trademarks of the Authors may NOT be used in any manner, including advertising or publicity pertaining to the Specification o
8、r its contents without specific, written prior permission. Title to copyright in the Specification will at all times remain with the Authors.No other rights are granted by implication, estoppel or otherwise.1.简介1.1V3.1与V3之间的变化2.消息格式2.1固定头部2.2可变头部2.3有效载荷2.4消息标识符2.5MQTT和UTF-82.6未使用的位3.命令消息3.1CONNECT3.
9、2CONNACK3.3PUBLISH3.4PUBACK3.5PUBREC3.6PUBREL3.7PUBCOMP3.8SUBSCRIBE3.9SUBACK3.10UNSUBSCRIBE3.11UNSUBACK3.12PINGREQ3.13PINGRESP3.14DISCONNECT4.消息流4.1交付质量级别和消息流4.2消息重传4.3消息排序5.附录A 主题通配符1. 简介该协议规范主要分为3个主要部分:对所有类型的数据包都通用的消息格式每种特定数据包的具体细节数据包如何在服务器和客户端之间传输在附录中将介绍如何主题通配符(topic wildcards)的使用方法。1.1 V3.1与V3之间
10、的变化MQTT V3.1中与MQTT V3之间的不同点如下所示:添加用户验证,用户名和密码现在可以在 CONNECT 数据包中一并发送。为解决一些安全问题,在 CONNACK 数据包中添加了新的返回码。当客户端发送未授权的 PUBLISH 或 SUBSCRIBE 命令时,客户端不会收到相应的通知,即客户端不知道命令不会被执行。而且即使命令未被执行,该MQTT流也应该正常完成。MQTT中的字符串现在支持完整的UTF-8字符集,而不仅仅是US-ASCII子集。V3.1中,通过 CONNECT 包传送的协议版本号仍然是“3”,与V3相比没有变化。现存的基于MQTT V3的服务器实现须通过正确考虑“剩
11、余长度(Remaining Length)字段”,以及相应地忽略多余的安全信息来接受来自V3.1协议的客户端的连接。2. 消息格式每个MQTT命令消息的消息头部都包含了一个固定头部。其中一些类型的消息可能还需要一个可变头部和一个有效载荷(可理解为消息体)。消息头部的具体格式将在后面章节中进行详细介绍。2.1 固定头部(Fixed header)每个MQTT命令消息的消息头部都包含一个固定头部。固定头部的格式如下表如示。Byte 1包含消息类型和标志(包括DUP,QoS level和RETAIN)字段。Byte 2包含剩余长度字段(至少1个字节,最多4个字节)。以下章节将详细介绍这些字段。所有数
12、据的值都是以big-endian(大端)模式存储:数据的高位字节存放在内存的低地址中,数据的低位字节存放在内存高地址中。一个16位字在内存中的存放顺序是先最高有效位(MSB),然后再最低有效位(LSB)。消息类型(Message Type)位置:byte 1, bits 7-4该字段为4-bit无符号值。当前协议版本中该字段的具体枚举值如下表所示。0:保留1:客户端请求连接服务器2:连接确认3:发布消息4:发布确认5:发布接收(有保证的交付第1部分)6:发布释放(有保证的交付第2部分)7:发布完成(有保证的交付第3部分)8:客户端订阅请求9:订阅确认10:客户端取消订阅请求11:取消订阅确认1
13、2:PING请求13:PING回复14:客户端断开连接15:保留标志位(Flags)固定头部第1个字节中剩余的部分包含DUP,QoS和RETAIN标志字段。相应bit位置如下表所示。DUP位置:byte 1,bit 3当客户端或服务器试图重发 PUBLISH、PUBREL、SUBSRIBE、UNSUBSCRIBE 消息时,该标志位要被置位(即设为1)。这适用于消息的QoS标志值大于0的情况,此时消息确认是必需的。当DUP位被置位时,可变头部将包含一个消息ID。消息的接收者应当将该标志视为该消息之前可能已收到的提示消息,而不该依赖于它进行消息重复检测。QoS位置:byte 1,bits 2-1该
14、标志位标明 PUBLISH 消息的交付质量级别。具体的QoS级别如下表所示。RETAIN位置:byte 1,bit 0该标志位只用于 PUBLISH 消息。当一个客户端发送一条 PUBLISH 消息给服务器,假设该消息所属的主题(topic)为topicA,如果该标志位被置位(1),服务器在将该条消息发布给当前的所有topicA的订阅者之后,还应当保持这条消息。当topicA出现了一个新的订阅者,则topicA的最后一条保持消息应当发给该订阅者。当然,如果不存在保持消息,则什么也不用发。当消息发布者以基于 “report by exception” 的方式发送消息时,这个功能就特别有用,因为这
15、种情况下,消息发送间隔往往较长。这个功能使得新的订阅者可以立刻收到之前保持的或上一个确定有效的消息。当服务器收到某个主题的 PUBLISH 消息时,对于之前已经订阅该主题的客户端,服务器将给这些客户端发送这一 PUBLISH 消息,发送前,服务器会将该消息的 RETAIN 标志置为0(即不置位),不管服务器之前收到该 PUBLISH 消息时其 RETAIN 标志是否被置位。这样做可以使得区分它接收到的 PUBLISH 消息是服务器之前保持的(RETAIN标志置位)还是即时收到的(RETAIN标志不置位)。保持消息应当在重启服务器后仍能保留。如果服务器收到有效载荷长度为0或重复主题的保持消息,服
16、务器可以删除该保持消息。剩余长度(Remaining Length)位置:byte 2(从byte 2,最大可至byte 5)该字段表示当前消息的剩余内容的字节数,包括可变头部和有效载荷的数据。该字段本身的字节数是根据可变头部和有效载荷的长度不同而变化的。该可变长度编码方案如下:每个字节的低7位(7-0位)编码剩余长度的数据,第8位表示后面是否还有编码剩余长度的字节。即每个字节编码128个值和一个“延续位”。所以只用一个字节时,最大只可表示127字节的长度。举例如下,十进制数字64只需用1个字节来编码,即0x40。 十进制数字321(=65 + 2x128)则需要用2个字节来编码,其中第1个字
17、节为1100 0001,该字节的低7位表示65,第8位表示后面还有字节;第2个字节为0000 0010,表示2x128。协议限制该字段最大为4个字节,这允许应用程序发送的最大消息长度为268435455(256MB),即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 (
18、 X 0 ) digit = digit OR 0x80 endif output digitwhile ( X 0 )其中,MOD是模运算符(在C语言中相当于%),DIV表示整数除法(在C语言中相当于/),OR是位或运算符(在C语言中相当于|)。相应地,剩余长度字段的解码算法如下所示:multiplier = 1value = 0do digit = next digit from stream value += (digit AND 127) * multiplier multiplier *= 128while (digit AND 128) != 0)其中,AND是位与运算符(在C语言
19、中相当于&)。当该解码算法终止,value等于剩余长度的字节数。值得注意的是,剩余长度编码不是可变头部的一部分。剩余长度的值不包括用于编码剩余长度的字节数。这部分“增加的长度”(1-3字节)是固定头部的一部分,而不属于可变头部。译者注:可认为剩余长度字段虽然是固定的,但该字段的长度却是变化的(1-4字节)。2.2 可变头部(Variable header)某些类型的MQTT命令消息还包含了一个可变头部,它位于固定头部和有效载荷之间。可变的剩余长度字段(1-4字节)不是可变头部的一部分。剩余长度字段的值不包括该字段本身的长度。该值只包括可变头部和有效载荷。更多细节可可见固定头部。可变头部中各个字
20、段的格式将在后续章节中进行详细介绍,介绍顺序与该字段在可变头部中的顺序一致。协议名称(Protocol name)协议名称字段只用于 MQTT CONNECT 消息的可变头部中。该字段以UTF编码方式显示协议名称:MQIsdp,大小写如上所示。协议版本(Protocol version)协议版本字段只用于 MQTT CONNECT 消息的可变头部中。该字段用8位无符号值来表示客户端所使用的协议修订级别。当前版本协议中该字段的值为3(0x03),如下表所示。连接标志(Connect flags)该字段用于 CONNECT 消息的可变头部中,占1字节,包括Clean session、Will、Wi
21、ll QoS和Retain标志。Clean session 标志位置:bit 1(在连接标志字节中,下同)如果没有被置位(即值为0),则当客户端断线时,服务器必须保存该客户端的订阅信息,包括断线期间发布的该客户端订阅的主题中交付质量级别为QoS 1和QoS2的消息,这样当客户端重连时,这部分消息能确保被送达到客户端。同时,服务器还必须保持客户端在断线的那个时刻正在传输中的消息的状态,直到客户端重新连接。如果被置位(即值为1),则服务器必须丢弃任何之前保持的该客户端的信息,将该连接视为“不存在(Clean)”。同时,当客户端断线时,服务器必须丢弃其所有状态。通常情况下,客户端会一直在其中一种模式
22、下操作,不会进行切换。该选择取决于具体应用的需求。一个 Clean session 客户端将不会收到过时的信息,且它每次重连时都需要重新订阅主题。而一个 non-clean session客户端则不会漏接任何它在断线时服务器发布的交付质量级别为QoS 1和QoS 2的消息。QoS 0级别的消息由于只是尽可能的交付,所以它永远不会被存储保持。这个标志以前被称为“Clean start”。因为这个标志其实是作用于整个会话期间的,而不只是在连接的开始阶段,为了明确这个事实,所以将它重命名为“Clean session”。服务器可以提供一种管理机制,当确定一个客户端将永远不会重新连接时,可以清除该客户
23、端的存储信息。连接标志中的第0位在目前协议版本中没有使用到,保留为将来使用。Will 标志位置:bit 2Will消息是指当服务器与客户端通信过程中出现故障或客户端在保活时间内没有与服务器保持正常交流时,服务器特意发给客户端的消息。当客户端通过发送 DISCONNECT 消息正常断开时,Will消息不会发送。如果Will标志被置位,则Will QoS标志和Will Retain标志的设置将会发生作用,同时,在有效载荷里必须填写Will主题和Will消息内容字段。Will标志的格式如下表所示。连接标志中的第0位在目前协议版本中没有使用到,保留为将来使用。Will QoS位置:bit 4-3Wil
24、l QoS标志用来设置当客户端异常离线时,服务器发送的Will消息的交付质量级别。Will消息的内容在客户端发送的 CONNECT 消息里的有效载荷里填写。如果Will标志被置位,则Will QoS字段必须填写,否则该字段的值将被忽略。Will QoS字段的可选值有0(0x00),1(0x01)和2(0x02),格式如下表所示。连接标志中的第0位在目前协议版本中没有使用到,保留为将来使用。Will Retain 标志位置:bit 5Will Retain标志指明服务器是否需要保持客户端异常离线时发送给客户端的Will消息。如果Will标志被置位,则Will Retain标志必须填写,否则其将被
25、忽略。该标志的格式如下表所示。连接标志中的第0位在目前协议版本中没有使用到,保留为将来使用。User name and password 标志位置:bit 6和bit 7客户端在连接服务器时可以指定用户名和密码,通过将用户名标志和密码标志(可选)置位表明在 CONNECT 消息的有效载荷里包含有用户名和密码。如果将用户名标志置位,则必须在有效载荷里填写用户名字段,否则用户名字段将被忽略。同样地,如果密码标志被置位,则必须在有效载荷里填写密码字段,否则密码字段将被忽略。只提供密码而不提供用户名是不合法的。连接标志中的第0位在目前协议版本中没有使用到,保留为将来使用。保活计时器(Keep Aliv
26、e timer)保活计时器用于MQTT CONNECT 消息的可变头部中。保活计时器定义了服务器收到客户端消息的最大时间间隔,它以秒为单位。它使得服务器不需要等待漫长的TCP/IP超时就可以检测与客户端的网络连接是否断开。客户端有义务在每个保活时间间隔内至少发送一条消息给服务器。如果这期间没有业务相关的消息要发送,客户端则发送一个 PINGREQ 消息给服务器,相应地服务器返回一个 PINGRESQ 消息给客户端。如果服务器在1.5个保活时间(可宽容0.5个保活时间)内都没有收到客户端的消息,则服务器将其视为客户端发送了一个 DISCONNECT 消息,并断开与客户端的连接。这个动作不影响客户
27、端的订阅。具体细节参见DISCONNECT。如果客户端在发送 PINGQ 后的一个保活时间内没有收到服务器发来的 PINGRESP 消息,则客户端可以关闭TCP/IP套接字连接。保活计时器用2个字节来表示,时间单位为秒。实际设定的值由特定应用决定,不过通常它的值都设为数分钟,最大值接近18个小时。如果设为0,则表示客户端不断线。保活计时器的格式如下表所示。2个字节的顺序为先 MSB,再 LSB(大端模式)。连接返回码(Connect return code)连接返回码用于 CONNACK 消息的可变头部中。这个字段用一个无符号字节来表示返回码。这些值的含义如下表所示。值为0的返回码通常表示连接
28、成功。主题名(Topic name)主题名用于 PUBLISH 消息的可变头部中。主题名决定消息要发送到哪个信息通道。订阅者使用主题名来决定他们要从哪些信息通道接收消息。主题名是一个UTF编码字符串。更多信息参见MQTT和UTF-8。主题名支持的最大字符度为32767。2.3 有效载荷(Payload)以下类型的MQTT命令消息拥有一个有效载荷:CONNECT该有效载荷包含了一个或多个UTF-8编码字符串。它们包括标识客户端的唯一标识符、Will主题和消息、要使用的用户名和密码。其中只有第一项是必选的,其余的取决于可变消息头部中的标志置位情况。SUBSCRIBE该有效载荷包含一系列要订阅的主题
29、名,以及每个主题的QoS级别。这些字符串都是UTF编码的。SUBACK该有效载荷包含一系列授权过的QoS级别。它们是服务器管理员允许授权给客户端订阅的各个主题的QoS级别。授权的QoS级别顺序与相应订阅的主题的顺序保持一致。PUBLISH该有效载荷只包含应用特定的数据。协议不对数据的属性和内容作任何假设,协议把消息的这部分内容视为一个BLOB。如果你想要对有效载荷数据进行压缩,你必须自己在有效载荷里定义合适的标志来处理压缩事宜。你不能在固定状况或可变头部里定义与特定应用相关的标志。2.4 消息标识符(Message Identifiers)消息标识符用于以下MQTT消息的可变头部中:PUBLI
30、SH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK。消息标识符(消息ID)字段只存在于固定头部中QoS标志值为1或2的消息中。更多信息可参见交付质量级别和消息流。消息ID用16位无符号整数来表示,在同一个方向上的在传消息ID必须是唯一的。它通常是逐个消息递增的,但不强制如此。客户端与它所连接的服务器一样,都需要维护自己的消息ID列表,二者的消息ID列表互不影响。客户端在发送一个消息ID为1的 PUBLISH 消息的同时也有可能收到来自服务器的消息ID为1的 PUBLISH 消息。表示消息ID的2个字节的顺序
31、为先 MSB,再 LSB(大端模式)。不要使用值为0的消息ID。它是作为无效消息ID保留的。2.5 MQTT和UTF-8(MQTT and UTF-8)UTF-8是一种针对Unicode的可变长度字符编码,它优化了ASCII字符集的编码,以支持基于文本的通信。在MQTT中,字符串编码的头2个字节用来记录字符串的长度,如下表所示。字符串长度表示所有字符经过UTF-8编码后的字节数,而不是字符串中字符的个数。例如,经过UTF-8编码后的字符串OTWP如下表所示。Java中的writeUTF()和readUTF()数据流方法也使用这种格式。2.6 未使用的位(Unused bits)任何标明为未使用的位都应当置为0。3. 命令消息(Command messages)3.1 CONNECT - 客户端请
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1