MQTT协议(一)

  MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约、轻量,易于使用,针对受限环境(带宽低、网络延迟高、网络通信不稳定),可以简单概括为物联网打造,官方总结特点如下:

1.使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
2. 对负载内容屏蔽的消息传输。
3. 使用 TCP/IP 提供网络连接。
4. 有三种消息发布服务质量:
    “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
    “至少一次”,确保消息到达,但消息重复可能会发生。
    “只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
5. 小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量。
6. 使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。

MQTT 3.1协议在线版本: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html

官方下载地址: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/MQTT_V3.1_Protocol_Specific.pdf

PDF版本,42页,不算多。

目前MQTT大家都用在了手机推送,可能还有很多的使用方式,有待进一步的探索。

固定头部

固定头部,使用两个字节,共16位:

bit76543210
byte 1Message TypeDUP flagQoS levelRETAIN
byte 2Remaining Length

 

 

 

  第一个字节(byte 1)

  消息类型(4-7),使用4位二进制表示,可代表16种消息类型:

MnemonicEnumerationDescription
Reserved0Reserved
CONNECT1Client request to connect to Server
CONNACK2Connect Acknowledgment
PUBLISH3Publish message
PUBACK4Publish Acknowledgment
PUBREC5Publish Received (assured delivery part 1)
PUBREL6Publish Release (assured delivery part 2)
PUBCOMP7Publish Complete (assured delivery part 3)
SUBSCRIBE8Client Subscribe request
SUBACK9Subscribe Acknowledgment
UNSUBSCRIBE10Client Unsubscribe request
UNSUBACK11Unsubscribe Acknowledgment
PINGREQ12PING Request
PINGRESP13PING Response
DISCONNECT14Client is Disconnecting
Reserved15Reserved

 

 

 

 

 

 

 

 

 

 

  除去0和15位置属于保留待用,共14种消息事件类型。

  DUP flag(打开标志)

  保证消息可靠传输,默认为0,只占用一个字节,表示第一次发送。不能用于检测消息重复发送等。只适用于客户端或服务器端尝试重发PUBLISH, PUBREL, SUBSCRIBE 或 UNSUBSCRIBE消息,注意需要满足以下条件:

   当QoS > 0
   消息需要回复确认

  此时,在可变头部需要包含消息ID。当值为1时,表示当前消息先前已经被传送过。

  QoS(Quality of Service,服务质量)

  使用两个二进制表示PUBLISH类型消息:

QoS valuebit 2bit 1Description
000至多一次发完即丢弃<=1
101至少一次需要确认回复>=1
210只有一次需要确认回复=1
311待用,保留位置

 

 

 

  RETAIN(保持)

  仅针对PUBLISH消息。不同值,不同含义:

  1:表示发送的消息需要一直持久保存(不受服务器重启影响),不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。

  备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送。

  0:仅仅为当前订阅者推送此消息。

  假如服务器收到一个空消息体(zero-length payload)、RETAIN = 1、已存在Topic name的PUBLISH消息,服务器可以删除掉对应的已被持久化的PUBLISH消息。

  Remaining Length(剩余长度)

  在当前消息中剩余的byte(字节)数,包含可变头部和负荷(内容)

  单个字节最大值:01111111,16进制:0x7F,10进制为127。

  MQTT协议规定,第八位(最高位)若为1,则表示还有后续字节存在。

  MQTT协议最多允许4个字节表示剩余长度。最大长度为:0xFF,0xFF,0xFF,0x7F,二进制表示为:11111111,11111111,11111111,01111111,十进制:268435455  byte=261120KB=256MB=0.25GB 四个字节之间值的范围:

DigitsFromTo
10 (0x00)127 (0x7F)
2128 (0x80, 0x01)16 383 (0xFF, 0x7F)
316 384 (0x80, 0x80, 0x01)2 097 151 (0xFF, 0xFF, 0x7F)
42 097 152 (0x80, 0x80, 0x80, 0x01)268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

 

 

 

 

  其实换个方式理解:第1字节的基数是1,而第2字节的基数:128,以此类推,第三字节的基数是:128*128=2的14次方,第四字节是:128*128*128=2的21次方;

例如,需要表达321=2*128+65.(2字节):10100001 0000 0011.

  (和我们理解的低位运算放置顺序不一样,第一个字节是低位,后续字节是高位,但字节内部本身是低位右边,高位左边)。

 

可变头部

固定头部仅定义了消息类型和一些标志位,一些消息的元数据,需要放入可变头部中。可变头部内容字节长度 + Playload/负荷字节长度 = 剩余长度。

可变头部,包含了协议名称,版本号,连接标志,用户授权,心跳时间等内容。

可变头部居于固定头部和payload中间。

可变剩余长度(remaing length)不是可变头部的一部分,当然该长度值也是从可变头部开始计算,包含可变头部的长度+payload的长度。

可变头部的字段如下:

  协议名称: MQTT CONNECT message. UTF编码:如 MQIsdp, capitalized.

  协议版本:8位无符号,当前使用:3 (0x03),如下:

bit76543210
 Protocol Version
 00000011

 

 

  Connect flags

  Clean session, Will, Will QoS, Retain flags 该字段的设置

  一个字节表示,除了第1位是保留未使用,其它7位都具有不同含义。

  业务上很重要,对消息总体流程影响很大,需要牢记。

  Clean session flag

  Position: bit 1 ,连接标志.

  0:server需要存储client的订阅。包括存储Qos 1和2的订阅主题(当client重连时能将消息发送);当连接丢失的时候 服务器必须维护正在发送的消息的状态直到客户端重新连接到服务器。

  1:server MUST忽略之前维护关于client的信息,并且将该connection当成clean的。server MUST 忽略任何client断开的状态。

 

  原文翻译不能,所以参考了下一位大牛的表达:

  0,表示如果订阅的客户机断线了,要保存为其要推送的消息(QoS为1和QoS为2),若其重新连接时,需将这些消息推送(若客户端长时间不连接,需要设置一个过期值)。 
  1,断线服务器即清理相关信息,重新连接上来之后,会再次订阅。

  Will Flag

  定义了客户端(没有主动发送DISCONNECT消息)出现网络异常导致连接中断的情况下,服务器需要做的一些措施

  简而言之,就是客户端预先定义好,在自己异常断开的情况下,所留下的最后遗愿(Last Will),也称之为遗嘱(Testament)。 这个遗嘱就是一个由客户端预先定义好的主题和对应消息,附加在CONNECT的可变头部中,在客户端连接出现异常的情况下,由服务器主动发布此消息。

  只有在Will Flag位为1时,Will Qos和Will Retain才会被读取,此时消息体Playload中要出现Will Topic和Will Message具体内容,否则,Will QoS和Will Retain值会被忽略掉。

  Will Qos

  两位表示,和PUBLISH消息固定头部的QoS level含义一样。

  若标识了Will Flag值为1,那么Will QoS就会生效,否则会被忽略掉。

  Will RETAIN

  如果设置Will Flag,Will Retain标志就是有效的,否则它将被忽略。

  当客户端意外断开服务器发布其Will Message之后,服务器是否应该继续保存。这个属性和PUBLISH固定头部的RETAIN标志含义一样,这里先掠过。

  User name 和 password Flag:

  用于授权,两者要么为0要么为1,否则都是无效。都为0,表示客户端可自由连接/订阅,都为1,表示连接/订阅需要授权。

bit76543210
 User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReserved
 xxxxxx x

 

 

  Playload/消息体/负荷

  消息体主要是为配合固定/可变头部命令(比如CONNECT可变头部User name标记若为1则需要在消息体中附加用户名称字符串)而存在。

  CONNECT/SUBSCRIBE/SUBACK/PUBLISH等消息有消息体。PUBLISH的消息体以二进制形式对待。

  MQTT协议只允许在PUBLISH类型消息体中使用自定义特性,在固定/可变头部想加入自定义私有特性是不允许的。

  这也是为了协议免于流于形式,变得很分裂也为了兼顾现有客户端等。比如支持压缩等,那就可以在Playload中定义数据支持,在应用中进行读取处理。

  这部分会在后面详细论述。

  消息标识符/消息ID

  固定头中的QoS level标志值为1或2时才会在:PUBLISH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK等消息的可变头中出现。

  一个16位无符号位的short类型值(值不能为 0,0做保留作为无效的消息ID),仅仅要求在一个特定方向(服务器发往客户端为一个方向,客户端发送到服务器端为另一个方向)的通信消息中必须唯一。比如客户端发往服务器,有可能存在服务器发往客户端会同时存在重复,但不碍事。

  可变头部中,需要两个字节的顺序是MSB(Most Significant Bit) LSB(Last/Least Significant Bit),翻译成中文就是,最高有效位,最低有效位。最高有效位在最低有效位左边/上面,表示这是一个大端字节/网络字节序,符合人的阅读习惯,高位在最左边。

bit76543210
 Message Identifier MSB
 Message Identifier LSB

 

 

 

  最大长度可为: 65535

UTF-8编码

有关字符串,MQTT采用的是修改版的UTF-8编码,一般形式为如下:

bit76543210
byte 1String Length MSB
byte 2String Length LSB
bytes 3 ...Encoded Character Data

 

 

 

 

最后的结构如下:

 Description76543210
Fixed header/固定头部
  Message Type(1)DUP flagQoS levelRETAIN
byte 1
 0001xxxx
byte 2Remaining Length
Variable header/可变头部
Protocol Name
byte 1Length MSB (0)00000000
byte 2Length LSB (6)00000110
byte 3'M'01001101
byte 4'Q'01010001
byte 5'I'01001001
byte 6's'01110011
byte 7'd'01100100
byte 8'p'01110000
Protocol Version Number
byte 9Version (3)00000011
Connect Flags
 User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReserved
byte 10
1100111x
Keep Alive timer
byte 11Keep Alive MSB (0)00000000
byte 12Keep Alive LSB (10)00001010
Playload/消息体

Client Identifier(客户端ID)

1-23个字符长度,客户端到服务器的全局唯一标志,如果客户端ID超出23个字符长度,服务器需要返回码为2,标识符被拒绝响应的CONNACK消息。
处理QoS级别1和2的消息ID中,可以使用到。
必填项。

Will Topic

Will Flag值为1,这里便是Will Topic的内容。QoS级别通过Will QoS字段定义,RETAIN值通过Will RETAIN标识,都定义在可变头里面。

Will Message

Will Flag若设为1,这里便是Will Message定义消息的内容,对应的主题为Will Topic。如果客户端意外的断开触发服务器PUBLISH此消息。
长度有可能为0。
在CONNECT消息中的Will Message是UTF-8编码的,当被服务器发布时则作为二进制的消息体。

User Name

如果设置User Name标识,可以在此读取用户名称。一般可用于身份验证。协议建议用户名为不多于12个字符,不是必须。

Password

如果设置Password标识,便可读取用户密码。建议密码为12个字符或者更少,但不是必须。

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
心跳时间(Keep Alive timer)

  以秒为单位,定义服务器端从客户端接收消息的最大时间间隔。一般应用服务会在业务层次检测客户端网络是否连接,不是TCP/IP协议层面的心跳机制(比如开启SOCKET的SO_KEEPALIVE选项)。 一般来讲,在一个心跳间隔内,客户端发送一个PINGREQ消息到服务器,服务器返回PINGRESP消息,完成一次心跳交互,继而等待下一轮。若客户端没有收到心跳反馈,会关闭掉TCP/IP端口连接,离线。 16位两个字节,可看做一个无符号的short类型值。最大值,2^16-1 = 65535秒 = 18小时。最小值可以为0,表示客户端不断开。一般设为几分钟,比如微信心跳周期为300秒。

  Will Message编码

Will Message在CONNECT Payload/消息体中,使用UTF-8编码。假设内容为“abcd”,大概如下:

 Description76543210
byte 1Length MSB (0)00000000
byte 2Length LSB (4)00000100
byte 3'a' (0x61)01100001
byte 4'b' (0x62)01100010
byte 5'c' (0x63)01100011
byte 6'd' (0x64)01100100

 

 

 

 

 

 

有一点需要记住,PUBLISH的Payload/消息体中以二进制编码保存。

某刻客户端异常关闭触发服务器会PUBLISH此消息。那么服务器会直接把byte3-byte6之间字符取出,保存为二进制,附加到PUBLISH消息体中,大概存储如下:

 

 

 

 

 

MQTT V3.1--我的理解 - leeying - 博客园 http://www.cnblogs.com/leeying/p/3791077.html

 

 

转载于:https://www.cnblogs.com/wujing-hubei/p/6088635.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值