MQTT协议笔记之订阅
前言
记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了。
SUBSCRIBE
一般来讲,客户端在成功建立TCP连接之后,发送CONNECT消息,在得到服务器端授权允许建立彼此连接的CONNACK消息之后,客户端会发送SUBSCRIBE消息,订阅感兴趣的Topic主题列表(至少一个主题),一个完整示范如下:
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
|---|---|---|---|---|---|---|---|---|---|---|
| Fixed header/固定头部 | ||||||||||
| byte 1 | Message Type(8) | DUP flag | QoS level | RETAIN | ||||||
| 1 | 0 | 0 | 0 | 0 | 0 | 1 | x | |||
| byte 2 | Remaining Length | |||||||||
| 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 | |
| Playload/消息体 | ||||||||||
| 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 | |
| Requested QoS | ||||||||||
| byte 6 | Requested QoS (1) | x | x | x | x | x | x | 0 | 1 | |
| Topic Name | ||||||||||
| byte 7 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
| byte 8 | Length LSB (3) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
| byte 9 | 'c' (0x63) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
| byte 10 | '/' (0x2F) | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | |
| byte 11 | 'd' (0x64) | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | |
| Requested QoS | ||||||||||
| byte 12 | Requested QoS (2) | x | x | x | x | x | x | 1 | 0 | |
固定头部
Qos Level,可根据实际情况进行调整为0/1/2等。一般设为0表示最多一次。客户端可设置OoS Level值。 DUP flag,值为0表示第一次发送。
可变头部
因为上面示范QoS level值为1,因此需要客户端传递消息ID,16位,无符号的short类型。
消息体
订阅的主题名称采用修改版UTF-8编码,然后紧跟着对应的QoS值。下面的次序,可能更为形象:
| Topic name | "a/b" |
| Requested QoS | 1 |
| Topic name | "c/d" |
| Requested QoS | 2 |
订阅者的Topic name支持通配符#和+ :
- #支持一个主题内任意级别话题
- +只匹配一个主题级别的通配符
eg:
finance/stock/#
finance/sotkc/ibm/+
都是有效,更具体规则,请参阅协议附加部分。
在服务器接收处理时,按照顺序读取即可:
String topicName = readUTF();
int qosVal = read();
服务器可以发送QoS不大于客户端设置OoS的消息,尤其是服务器不提供良好的持久化机制的时候。
SUBACK
服务器会对发出SUBSCRIBE的消息返回一个确认消息。
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
|---|---|---|---|---|---|---|---|---|---|
| Fixed header/固定头部 | |||||||||
| byte 1 | Message type (9) | DUP flag | QoS flags | RETAIN | |||||
| 1 | 0 | 0 | 1 | x | x | x | x | ||
| byte 2 | Remaining Length | ||||||||
| 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 |
| Playload/消息体 | |||||||||
| byte 1 | Granted QoS (0) | x | x | x | x | x | x | 0 | 0 |
| byte 1 | Granted QoS (2) | x | x | x | x | x | x | 1 | 0 |
可变头部
Message Identifier,服务器需要附加,客户端需要处理。
消息体
QoS,为服务器根据实际情况授予的QoS级别列表,和客户端发送的SUBSCRIBE的订阅Topic Name顺序完全一致。
客户端订阅几个TOPIC,服务器端一一给出各个TOPIC的QoS具体值。
UNSUBSCRIBE
服务器需要支持客户端取消订阅功能,UNSUBSCRIBE消息格式和SUBSCRIBE消息格式差不多,除了消息类型不同,消息体中没有了QoS字节,其它没有区别。
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
|---|---|---|---|---|---|---|---|---|---|---|
| Fixed header/固定头部 | ||||||||||
| byte 1 | Message Type(10) | DUP flag | QoS level | RETAIN | ||||||
| 1 | 0 | 1 | 0 | 0 | 0 | 1 | x | |||
| byte 2 | Remaining Length | |||||||||
| 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 | |
| Playload/消息体 | ||||||||||
| 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 | |
| Topic Name | ||||||||||
| byte 6 | Length MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
| byte 7 | Length LSB (3) | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
| byte 8 | 'c' (0x63) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | |
| byte 9 | '/' (0x2F) | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | |
| byte 10 | 'd' (0x64) | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | |
可变头部的消息ID的出现还是由固定头部的QoS Level(1)决定是否存在。
一般来讲,客户端发布退订,服务器端需要返回退订确认。
MQTT没讲是否允许客户端退订所有TOPIC。
UNSUBACK
服务器返回的UNSUBSCRIBE消息UNSUBACK相应很简单,没有消息体。
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
|---|---|---|---|---|---|---|---|---|---|
| Fixed header/固定头部 | |||||||||
| byte 1 | Message type (9) | DUP flag | QoS flags | RETAIN | |||||
| 1 | 0 | 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 |
小结
订阅部分,共有四个消息,分别一一对应。
| 命令 | 响应 | 备注 | 建议 |
|---|---|---|---|
| SUBSCRIBE | SUBACK | 协议没有涉及最多运行订阅TOPIC数目,隐藏的隐患 | 建议至多10个 |
| UNSUBSCRIBE | UNSUBACK | 是否可以退订所有订阅,不详 | 建议保留至少一个Topic |
MQTT协议笔记之订阅的更多相关文章
- MQTT协议笔记之发布流程
MQTT协议笔记之发布流程 前言 这次要讲到客户端/服务器的发布消息行为,与PUBLISH相关的消息类型,会在这里看到. PUBLISH 客户端发布消息经由服务器分发到所有对应的订阅者那里.一个订阅者 ...
- MQTT协议笔记之头部信息
前言 记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了. SUBSCRIB ...
- 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协议笔记之mqtt.io项目TCP协议支持
前言 MQTT定义了物联网传输协议,其标准倾向于原始TCP实现.构建于TCP的上层协议堆栈,诸如HTTP等,在空间上多了一些处理路径,稍微耗费了CPU和内存,虽看似微乎其微,但对很多处理能力不足的嵌入 ...
- MQTT协议笔记之连接和心跳
前言 本篇会把连接(CONNECT).心跳(PINGREQ/PINGRESP).确认(CONNACK).断开连接(DISCONNECT)和在一起. CONNECT 像前面所说,MQTT有关字符串部分采 ...
- MQTT协议-----订阅
MQTT协议笔记之订阅 http://www.blogjava.net/yongboy/archive/2014/04/12/412351.html MQTT - chszs的专栏 h ...
- MQTT协议学习总结
一.MQTT介绍 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通 ...
随机推荐
- pip下载保存Python包,pip离线安装
新版pip下载安装包命令: pip download -r requirements.txt -d /tmp/paks/ 在linux下 1.下载指定的包到指定文件夹. ...
- BloomFilter——大规模数据处理利器[转]
原文链接:原文 Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合. 一. 实 ...
- 消息队列(RabbitMQ、zorneQ、metaQ、activeMQ)
术语: AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计. JMS, ...
- MongoDB之分片
本文介绍分片的思想和MongoDB中的实现方法. 首先须要介绍一些主要的概念. 分片 分片.也叫做分区.是一种经常使用的数据库优化技术.其含义就是将数据拆分,将数据分散到不同机器上的过程.这样就能够使 ...
- 清除DataGridView显示的数据
一.DataGridView未绑定数据时清空数据 this.dgv_PropDemo.DataSource = null 二.DataGridView绑定数据时清空数据 DataGridView绑定了 ...
- 利用层的table-row、table-cell属性进行页面布局
利用层的table-row.table-cell属性可以进行等高.宽度自适应页面布局,这是参看了<我所知道的几种display:table-cell的应用>及<基于display:t ...
- altium designer应用技巧---cyclone IV代芯片底部焊盘问题
首先对于 altera 公司的FPGA芯片来讲,在cyclone III代以上,芯片的底部增加了一 个焊盘,很多工程师往往以为是散热用,其实不然,底部焊盘需要接地(altera手册上面 明确规定,Th ...
- e553. 作为浏览器访问URL
// See also e551 精简的Applet try { URL url = new URL(getDocumentBase(), "http://hostname.com/page ...
- JMeter使用记录2 -- Web測试
Web測试用例 新建线程组.配置起3线程,循环1次.1秒启动全部线程.进行login.循环1个主要页面的读写,并对另外一个主要页面进行读操作,最后logout并在aggregate graph/gra ...
- BinarySearchTree二叉搜索树的实现
/* 二叉搜索树(Binary Search Tree),(又:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; ...