MQTT协议笔记之发布流程
MQTT协议笔记之发布流程
前言
这次要讲到客户端/服务器的发布消息行为,与PUBLISH相关的消息类型,会在这里看到。
PUBLISH
客户端发布消息经由服务器分发到所有对应的订阅者那里。一个订阅者可以订阅若干个主题(Topic name),但一个PUBLISH消息只能拥有一个主题。
消息架构一览:
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
---|---|---|---|---|---|---|---|---|---|---|
Fixed header/固定头部 | ||||||||||
byte 1 | Message Type(3) | DUP flag | QoS level | RETAIN | ||||||
0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | |||
byte 2 | Remaining Length | |||||||||
Variable header/可变头部 | ||||||||||
Topic name | ||||||||||
byte 1 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 2 | Length LSB (3) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
byte 3 | 'a' (0x61) | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | |
byte 4 | '/' (0x2F) | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | |
byte 5 | 'b' (0x62) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | |
Message Identifier | ||||||||||
byte 6 | Message ID MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
byte 7 | Message ID LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | |
Playload/消息体 | ||||||||||
BLOB,二进制对象形式。二进制具体包含的内容和格式,可有应用程序自身定义。若消息体为空(0长度)也是可能的。 |
固定头部
DUP flag,设为0,表示当前为第一次发送。
RETAIN flag,只有在PUBLISH消息中才有效。
- 1:表示发送的消息需要一直持久保存,不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。 备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送,不是所有。
- 0:仅仅为当前订阅者推送此消息。
可变头部
Topic name,UTF-8编码字符串形式,不支持通配符!
消息体
一般作为UTF-8编码写入接口,但不排除自定义的消息格式。
空的消息体(zero-length)的PUBLISH消息也可以是合法的。
当服务器接收到空消息体(zero-length payload)、retain = 1、具有topic name的一个PUBLISH特殊消息,表示同时满足retain = 1、相同topic name的这两个特征的被持久化PUBLISH消息,可被删除。
Response/响应
固定头部QoS level决定了消息中间件针对发布者具体需要响应的内容:
QoS Level | Expected response |
QoS 0 | None |
QoS 1 | PUBACK |
QoS 2 | PUBREC |
备注:仅仅针对发布PUBLISH消息的发布者。
Actions:
无论是订阅者还是服务器接收到PUBLISH消息之后,需要根据QoS level执行不同动作。
QoS Level | Expected Action |
QoS 0 | 发送到所有感兴趣者 |
QoS 1 | 持久化记录下来,发送到所有感兴趣的参与者,返回一个PUBACK消息给发送者 |
QoS 2 | 持久化记录下来,暂时不发送所有感兴趣的参与者,返回一个PUBREC消息给发送者 |
如果服务器收到PUBLISH消息,参与者指的是订阅者。如果订阅者收到PUBLISH消息,参与者就是服务器。 需要注意:
- 发布者发布的PUBLISH消息发送到服务器,在payload/消息体处可能夹带有私货,可能含有自定义的数据 格式
- 若兼容MQTT客户端,经由服务器分发到所有对应订阅者处只能是规规矩矩的PUBLISH消息,并且固定头部的RETAIN标志不能被设置成有效值1
授权
未经授权的发布者提交的PUBLISH消息,服务器会忽略掉,客户端不会被通知。
PUBACK
作为订阅者/服务器接收(QoS level = 1)PUBLISH消息之后对发送者的响应,整个消息不复杂。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定头部 | |||||||||
byte 1 | Message type (4) | DUP flag | QoS flags | RETAIN | |||||
0 | 1 | 0 | 0 | x | x | x | x | ||
byte 2 | Remaining Length (2) | ||||||||
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ||
Variable header/可变头部 | |||||||||
Message Identifier | |||||||||
byte 1 | Message ID MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | Message ID LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
虽没有消息体,但可变头部附加一个16位的无符号short类型。
PUBREC
字面意思为Assured publish received,作为订阅者/服务器对QoS level = 2的发布PUBLISH消息的发送方的响应,确认已经收到,为QoS level = 2消息流的第二个消息。 和PUBACK相比,除了消息类型不同外,其它都是一样。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定头部 | |||||||||
byte 1 | Message type (5) | DUP flag | QoS flags | RETAIN | |||||
0 | 1 | 0 | 1 | x | x | x | x | ||
byte 2 | Remaining Length (2) | ||||||||
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ||
Variable header/可变头部 | |||||||||
Message Identifier | |||||||||
byte 1 | Message ID MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | Message ID LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
无论是订阅者还是服务器,在消费PUBREC消息之后需要发送一个PUBREL消息给发送者(和PUBREC具有同样的消息ID),确认已收到。
PUBREL
Qos level = 2的协议流的第三个消息,有PUBLISH消息的发布者发送,参与方接收。完整示范如下:
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定头部 | |||||||||
byte 1 | Message type (6) | DUP flag | QoS flags | RETAIN | |||||
0 | 1 | 1 | 0 | 0 | 0 | 1 | x | ||
byte 2 | Remaining Length (2) | ||||||||
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ||
Variable header/可变头部 | |||||||||
Message Identifier | |||||||||
byte 1 | Message ID MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | Message ID LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
QoS level 1,PUBREL消息要求如此。
DUP flag 为0,表示消息第一次被发送。
毫无疑问,剩余长度为2个byte长度。
可变头部中,消息ID和发布者接收到的PUBREC所包含的消息ID是一致的。
动作:
- 服务器接收到发布者(a)的PUBREL消息,此时服务器让发布者(a)刚才发布PUBLISH消息可用,发送此PUBLISH消息给所有订阅此主题的订阅者,然后发送PUBCOMP消息给发布者(a)
- 可变头部包含消息ID和服务器接收的PUBREL消息ID是一致的。 一个订阅者接收到PUBREL消息,订阅者使PUBLISH消息可用,然后反馈一个PUBCOMP消息给服务器
PUBCOMP
作为QoS level = 2消息流第四个,也是最后一个消息,由收到PUBREL的一方向另一方做出的响应消息。
完整的消息一览,和PUBREL一致,除了消息类型。
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
Fixed header/固定头部 | |||||||||
byte 1 | Message type (7) | DUP flag | QoS flags | RETAIN | |||||
0 | 1 | 1 | 1 | x | x | x | x | ||
byte 2 | Remaining Length (2) | ||||||||
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ||
Variable header/可变头部 | |||||||||
Message Identifier | |||||||||
byte 1 | Message ID MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 2 | Message ID LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
当客户端接收一个PUBCOMP消息时,客户端摒弃原来的消息,因为它已经成功发送消息到服务器。
小结
消息的发布和确认等一些流程,主要是跟消息发布者所设定的QoS level有关;稍加整理,绘制了下面一张图,理解起来可能会更清晰些:
上图针对的是客户端发布消息到服务器端的方向。
为了确保消息已经成功传递过去,只有收到了确认,才会让人特别放心。
在QoS level = 2时,通信双方都需要知道各自的确认流程以及所处阶段等,交互很多,数据量大的情况下,可能会造成数据线路传递拥塞。服务器选择QoS = 0/1,大部分情况都是可以应对的。 比如重要消息,就要确保对方都要收到,然后彼此确认,OK,这个消息是真实、有效的。
无论Qos level为0、1,还是2,服务器(具备所有条件都满足之后)总要把收到的具体内容和topic组装成一个新的PUBLISH Message(也不一定要重新构造,但要求推送的PUBLISH消息,一定要具有明确的主题和内容,RETAIN标志不能设置为1)推送到所有感兴趣的订阅者。
嗯,消息的发布来源别忘记还有可能来自CONNECT消息中的Will Topic和Will Message,若是设置了Will flag标记的话。
原文 http://www.blogjava.net/yongboy/archive/2014/02/10/409689.html
MQTT协议笔记之发布流程的更多相关文章
- MQTT协议笔记之订阅
前言 记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了. SUBSCRIB ...
- MQTT协议笔记之头部信息
前言 记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了. SUBSCRIB ...
- 深度剖析MQTT协议的整个通信流程
http://www.elecfans.com/d/587483.html MQTT,目前物联网的最主要的协议,基本所有收费的云平台都是基于MQTT协议,比如机智云,和所有的开放云平台比如中国移动的o ...
- MQTT协议笔记之消息流
前言 前面的笔记已把所有消息类型都过了一遍,这里从消息流的角度尝试解读一下. 网络故障 在任何网络环境下,都会出现一方连接失败,比如离开公司大门那一刻没有了WIFI信号.但持续连接的另一端-服务器可能 ...
- MQTT协议笔记之mqtt.io项目HTTP协议支持
前言 MQTT协议诞生之初,就未曾考虑通过HTTP传输.这也正常,网络受限.不稳定网络不太适合HTTP(2G/3G网络大家使用WAP不也OK嘛).在网络较为充裕的桌面端而言,虽纯文本对比二进制而言没多 ...
- MQTT协议笔记之mqtt.io项目Websocket协议支持
前言 MQTT协议专注于网络.资源受限环境,建立之初不曾考虑WEB环境,倒也正常.虽然如此,但不代表它不适合HTML5环境. HTML5 Websocket是建立在TCP基础上的双通道通信,和TCP通 ...
- MQTT协议笔记之连接和心跳
前言 本篇会把连接(CONNECT).心跳(PINGREQ/PINGRESP).确认(CONNACK).断开连接(DISCONNECT)和在一起. CONNECT 像前面所说,MQTT有关字符串部分采 ...
- MQTT协议笔记之mqtt.io项目TCP协议支持
前言 MQTT定义了物联网传输协议,其标准倾向于原始TCP实现.构建于TCP的上层协议堆栈,诸如HTTP等,在空间上多了一些处理路径,稍微耗费了CPU和内存,虽看似微乎其微,但对很多处理能力不足的嵌入 ...
- MQTT协议-----订阅
MQTT协议笔记之订阅 http://www.blogjava.net/yongboy/archive/2014/04/12/412351.html MQTT - chszs的专栏 h ...
随机推荐
- usb 转 uart cp210x 驱动解析
USB 转 uart (cp210x.c) 驱动解析 * usb_serial_driver 结构体解析 include/linux/usb/serial.h /** 描述一个usb 串口设备驱动 * ...
- java中常见的异常(转)
1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对 ...
- 应用层timer_libc_posix timer
应用层除了通过setitimer/getitimer设置获取timer外,还可通过timer_create()等一系列函数实现应用层timer功能. 应用流程 The timers created b ...
- 看板与Scrum:哪个更适合你的团队?
敏捷是理想型指标和原则,看板和Scrum是帮助团队坚持敏捷原则并完成工作的基本框架.本文详细介绍了在Scrum和看板之间做出选择时要考虑的关键因素,以及如果我们无法做出决定时该怎么办. Scrum和看 ...
- 关于Cocos2d-x属性和引用
在HelloScene.h文件里面的Private定义一个Size类型的变量visibleSize,然后在HelloScene.cpp里面引用HelloScene.h,再在HelloScene::in ...
- 多媒体开发之h264的三种字节流格式---annexb 哥伦布/mp4 以及还有一种rtp传输流格式
------------------------------------author:pkf ------------------------------------------time:2015-1 ...
- NPOI帮助类(Excel转DataTable、DataTable转Excel)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using NPOI.SS. ...
- Hibernate学习(1):查询demo
1.数据库(mysql)创建脚本 DROP TABLE IF EXISTS role; CREATE TABLE IF NOT EXISTS `role`( `id` ) NOT NULL AUTO_ ...
- c++ define的用法(转)
#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用 ...
- Java中的各种加密算法
Java中为我们提供了丰富的加密技术,可以基本的分为单向加密和非对称加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中,是否被篡改过. BASE64 严格地说,属于编码格式,而非加密算法 ...