http://blog./28624388/viewspace-1176994/ 2014
MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约、轻量,易于使用,针对受限环境(带宽低、网络延迟高、网络通信不稳定),可以简单概括为物联网打造,官方总结特点如下:
1.使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
2. 对负载内容屏蔽的消息传输。
3. 使用 TCP/IP 提供网络连接。
4. 有三种消息发布服务质量:
“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
“至少一次”,确保消息到达,但消息重复可能会发生。
“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
5. 小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量。
6. 使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。
消息格式
一:固定头部
MQTT的消息包含着一个有两个字节大小的固定头部
bit
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
byte 1
|
Message Type
|
DUP flag
|
QoS level
|
RETAIN
|
byte 2
|
Remaining Length
|
二:消息类型(Message Tpe)
消息类型(4-7),使用4位二进制表示,可代表16种消息类型:
Mnemonic
|
Enumeration
|
Description
|
Reserved
|
0
|
Reserved----保留待用
|
CONNECT
|
1
|
Client request to connect to Server----客户端连接请求
|
CONNACK
|
2
|
Connect Acknowledgment----连接反馈
|
PUBLISH
|
3
|
Publish message-----发布消息
|
PUBACK
|
4
|
Publish Acknowledgment-----发布反馈
|
PUBREC
|
5
|
Publish Received (assured delivery part 1)----发布消息被接收
|
PUBREL
|
6
|
Publish Release (assured delivery part 2)
|
PUBCOMP
|
7
|
Publish Complete (assured delivery part 3)----发布消息完成
|
SUBSCRIBE
|
8
|
Client Subscribe request----客户端订阅
|
SUBACK
|
9
|
Subscribe Acknowledgment----订阅反馈
|
UNSUBSCRIBE
|
10
|
Client Unsubscribe request----客户端解除订阅
|
UNSUBACK
|
11
|
Unsubscribe Acknowledgment----接触订阅反馈
|
PINGREQ
|
12
|
PING Request-------心跳检测
|
PINGRESP
|
13
|
PING Response----心跳反馈
|
DISCONNECT
|
14
|
Client is Disconnecting----客户端断开连接
|
Reserved
|
15
|
Reserved----保留待用
|
三:DUP flag(打开标志)
保证消息可靠传输,默认为0,只占用一个字节,表示第一次发送。不能用于检测消息重复发送等。只适用于客户端或服务器端尝试重发PUBLISH, PUBREL, SUBSCRIBE 或 UNSUBSCRIBE消息,注意需要满足以下条件:
当QoS > 0
消息需要回复确认
此时,在可变头部需要包含消息ID。当值为1时,表示当前消息先前已经被传送过。
四:QoS(Quality of Service,服务质量)
使用两个二进制表示PUBLISH类型消息:
QoS value
|
bit 2
|
bit 1
|
Description
|
0
|
0
|
0
|
至多一次
|
发完即丢弃
|
<=1
|
1
|
0
|
1
|
至少一次
|
需要确认回复
|
>=1
|
2
|
1
|
0
|
只有一次
|
需要确认回复
|
=1
|
3
|
1
|
1
|
待用,保留位置
|
五:RETAIN(保持)
仅针对PUBLISH消息。不同值,不同含义:
1:表示发送的消息需要一直持久保存(不受服务器重启影响),不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。
备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送。
0:仅仅为当前订阅者推送此消息。
假如服务器收到一个空消息体(zero-length payload)、RETAIN = 1、已存在Topic name的PUBLISH消息,服务器可以删除掉对应的已被持久化的PUBLISH消息。
六:QoS level决定的消息流
QoS level为Quality of Service level的缩写,翻译成中文,服务质量等级。
MQTT 3.1协议在"4.1 Quality of Service levels and flows"章节中,仅仅讨论了客户端到服务器的发布流程,不太完整。因为决定消息到达率,能够提升发送质量的,应该是服务器发布PUBLISH消息到订阅者这一消息流方向。
QoS level 0
至多发送一次,发送即丢弃。没有确认消息,也不知道对方是否收到。
Client
|
Message and direction
|
Server
|
QoS = 0
|
PUBLISH
---------->
|
Action: Publish message to subscribers then Forget
Reception: <=1
|
针对的消息不重要,丢失也无所谓。
网络层面,传输压力小。
QoS level 1
所有QoS level 1都要在可变头部中附加一个16位的消息ID。
SUBSCRIBE和UNSUBSCRIBE消息使用QoS level 1。
针对消息的发布,Qos level 1,意味着消息至少被传输一次。
发送者若在一段时间内接收不到PUBACK消息,发送者需要打开DUB标记为1,然后重新发送PUBLISH消息。因此会导致接收方可能会收到两次PUBLISH消息。针对客户端发布消息到服务器的消息流:
Client
|
Message and direction
|
Server
|
QoS = 1
DUP = 0
Message ID = x
Action: Store message
|
PUBLISH
---------->
|
Actions:
-
Store message
-
Publish message to subscribers
-
Delete message
Reception: >=1
|
Action: Discard message
|
PUBACK
<----------
|
Message ID = x
|
针对服务器发布到订阅者的消息流:
Server
|
Message and direction
|
Subscriber
|
QoS = 1
DUP = 0
Message ID = x
|
PUBLISH
---------->
|
Actions:
-
Store message
-
Make message available
Reception: >=1
|
|
PUBACK
<----------
|
Message ID = x
|
发布者(客户端/服务器)若因种种异常接收不到PUBACK消息,会再次重新发送PUBLISH消息,同时设置DUP标记为1。接收者以服务器为例,这可能会导致服务器收到重复消息,按照流程,broker(服务器)发布消息到订阅者(会导致订阅者接收到重复消息),然后发送一条PUBACK确认消息到发布者。
在业务层面,或许可以弥补MQTT协议的不足之处:重试的消息ID一定要一致接收方一定判断当前接收的消息ID是否已经接受过
但一样不能够完全确保,消息一定到达了。
QoS level 2
仅仅在PUBLISH类型消息中出现,要求在可变头部中要附加消息ID。
级别高,通信压力稍大些,但确保了仅仅传输接收一次。
先看协议中流程图,Client -> Server方向,会有一个总体印象:
Client
|
Message and direction
|
Server
|
QoS = 2
DUP = 0
Message ID = x
Action: Store message
|
PUBLISH
---------->
|
Action(a) Store message
or
Actions(b):
-
Store message ID
-
Publish message to subscribers
|
|
PUBREC
<----------
|
Message ID = x
|
Message ID = x
|
PUBREL
---------->
|
Actions(a):
-
Publish message to subscribers
-
Delete message
or
Action(b): Delete message ID
|
Action: Discard message
|
PUBCOMP
<----------
|
Message ID = x
|
Server -> Subscriber:
Server
|
Message and direction
|
Subscriber
|
QoS = 2
DUP = 0
Message ID = x
|
PUBLISH
---------->
|
Action: Store message
|
|
PUBREC
<----------
|
Message ID = x
|
Message ID = x
|
PUBREL
---------->
|
Actions:
|
|
PUBCOMP
<----------
|
Message ID = x
|
Server端采取的方案a和b,都包含了何时消息有效,何时处理消息。两个方案二选一,Server端自己决定。但无论死采取哪一种方式,都是在QoS level 2协议范畴下,不受影响。若一方没有接收到对应的确认消息,会从最近一次需要确认的消息重试,以便整个(QoS level 2)流程打通。
|