文章转载于https://www.cnblogs.com/hayasi/p/7792191.html

我们已经把相关的连接报文搞定了。笔者想来想去还是决定先讲解一下订阅报文(SUBSCRIBE )。如果传统的通信方式是客户端和服务端之间一般就直接传输信息。但是MQTT的通信方式是通过发布/订阅的方式进行的。笔者不知道他是否跟设计模式中的发布订阅模式有没有关系。可是他们思想却有一点相似之处。

客户端知道服务上有很多个主题。就好比如说有很多消息的分类一样子。有社会新闻、体育讲坛等。那么客户端只要找到自己感兴趣的进行订阅就可以了。一个客户端可以向服务器订阅多个主题。而所谓的发布就是客户端对不同的主题进行发布信息。即好比如新闻的发布者一样子。这个时候只要订阅这个主题的客户端就可以接收到来自服务端的新闻。我们的手机常常会接收到一些推送的信息。事实上有很多App应用都是用MQTT协议来进行的。所以不难看出服务端主要是负责客户端和客户端的之间信息的传输和信息管理。大至如图下

注意:发布者也是客户端。订阅者也是客户端

主题(Topic )

如果主题只是一个字符串值的话,那么显然会比较单调。这样子功能也显得比较无力。所以在主题上面就了所谓的分隔符和通配符的说法(个人想法)。分隔符的意思就是让主题可以分层次。就好如说主题“体育讲坛/篮球/NBA”。看到这样子的主题,请问一下你还有什么不明白的话。是不是感觉很有层次感。剩下只有一个问题?如果我们订阅了主题“体育讲坛/篮球/NBA”,并向主题“体育讲坛/篮球”发布一个信息。那么已经订阅主题“体育讲坛/篮球/NBA”的客户端们是不是可以接受到信息呢?反过来讲如果我们订阅了主题“体育讲坛/篮球”,向主题“体育讲坛/篮球/NBA”发信息,客户端们是否又能接受信息呢?

笔者就以HiveMQ作服务器来做一下上面的小实验。如下

客验结果显然是失败的——订阅主题“体育讲坛/篮球/NBA”的客户端根本收不到来自主题“体育讲坛/篮球“的发布信息。说明分隔符就是用于主题名的分层次。没有别的意思。

通过上面的实验我们知道如果想要收到NBA就是必须订阅主题“体育讲坛/篮球/NBA”。可是总是有一些人只要是篮球的新闻有喜欢。怎么办。通配符的功能就出来了。通配符有俩种——"+"和“#”。+为单层的通配符。表示当前这一层的全都合非。这样子以上面的说到的例子来做实验。我们订阅一个主题为“体育讲坛/篮球/+”。按照理解的意思就是只要是在“体育讲坛/篮球”的信息都是我们想要的。结果如下

我们可以看到笔者在“体育讲坛/篮球/NBA”和“体育讲坛/篮球/ABC”各发布了信息。结果他都能收到。那么如果我们对主题“体育讲坛/篮球”或是主题“体育讲坛/篮球/NBA/福州专场”发布信息呢?笔者试过了很可惜都不行。

记得我们上面说到有一些人只要跟篮球相关的都喜欢。可是如果使用通配符“+”是可以接近我们的要求。注意是接近。“+”通配符只是表示当前一层的。从当前的第二层就不行了。而本身的层也不算。就像上面的。只有篮球下的子一层才是合非的。讲到这里大家一定会想到用“#“通配符试试。没有错。“#“通配符就是表示当前本身和下面子层所有。如下

实验的结果很终满足了。

对于主题,在文档中有一个要求——主题不能以 ”#“ "+" "$" 为开头。对于”#“ ” +“的话,大家都好理解。那么”$“又是什么鬼。在文档我们可以看到这样子的字符"$SYS"。事实上他们是想说”$“开头的主题一般用于系统内部的一些主题。你们可以去找一些第三方的MQTT服务器。都会有很多以”$“开头的主题。

SUBSCRIBE报文

通过上面的介绍。笔者想你们一定对MQTT通信方式有了一定的概念。而本章的订阅报文就是用于告诉服务器我想要什么的主题了。通过前面几章的了解。我们知道报文的固定报头是少了的。笔者就以MQTT 3.1.1来介绍吧。如下

SUBSCRIBE报文的INT值是8。所以对应的二进制为1000。后面的DUP QOS RETAIN对应是0010。其中QOS是必须是01。对订阅者来讲,他一定希望自己的订阅是成功的。所以订阅报文的QOS是01就相当好理解了。如果不理解QOS是什么的话,请看一下前面几章。

订阅报文也有可变报头,可变报头只有一个消息ID。消息ID是从客端端开始分配的。笔者为什么样子认为呢?主要是看到客户端在发布信息的时候就要求消息ID。所以笔者才会觉得消息ID在客户端进行分配的。当然也不是什么报文都会消息ID的。但是有消息ID一般QOS大于0。

订阅报文的有效载荷里面存在了相关的订阅订题列表。前面说过可以支持一个客户端多个订阅。列表里面每有一主题项只有俩个值。一个表示主题名,一个表示服务质量要求(Requested QoS)。这里的服务质量要求(Requested QoS)和 固定报头的服务质量的值是一样子。但是用意却是不一样子。这里是指这个订阅者接收这主题的服务质量最大等级。举个列子吧。笔者订阅了一个主题主题“体育讲坛/篮球/NBA”,同时他的服务质量要求(Requested QoS)的值为1。这个时候有一个发布者在这个主题上发布一个服务质QOS为2。笔者还是可以收到这个发布者发来的信息。只是信息的服务质量QOS却变为1了。要明白QOS(1)和QOS(2)的执行行为是不样子的。这个后面章节会讲到。当然如果发布者在这个主题上发布一个服务质QOS为0。这就没有什么区别了。如下

对于有效载荷笔者这里就不多讲解了。也没有什么可说的。看文档的图片就够了如下。

宏观上:

微观上:

列表出我们可以看他订阅了俩个主题。一个主题”a/b“,一个主题”c/b“。上面列出大概的图片(宏观上)和比较细的图片(微观上)。如果看不懂也没有关系。笔者接下来会用代码来抓一包看看。相信在对照一下就明白列表出画的是什么。

现在让我们好好想想当服务器接收到来自客户端的订阅报文的时候要做些什么样子的反应呢?首先我们要明白如果服务端接收到一个订阅报文,第一步想到一定是查看订阅报文的格式是不是正确的。相关的主题名是不是为空的。主题名的写法是不是非法。这些一定离不开。当然对应的一些共有的验证笔者就不说了。一切没有问题的情况下,服务器会去看一下当前订阅者前面有没有订阅过相同的主题。如果有就替换当前的。如果没有就创建一下新的。然后服务器在根据当前主题查找一下符合保留的信息。如果有,就发送给当前的订阅者。然后发送一个订阅报文确定(SUBACK )。当然这前后没有规定。先发送一个订阅报文确定(SUBACK ),在处理保留的信息也是可以的。

注意:在发送符合保留的信息就要对QOS进行处理。上面笔者也讲过了。

SUBACK 报文

当服务端处理SUBSCRIBE报文的时候,都会生成一个SUBACK 报文来回应订阅者。笔者这里不想对他太过的讲解。他的内容也很简单。如下

对于SUBACK 报文的可变报头里面也只有一个消息ID。而且跟SUBSCRIBE报文的消息ID是一样子的。有效载何的内容存放是订阅主题的服务质量要求(Requested QoS)。笔者在MQTT 3.1 文档时面可以看到有多个主题的列子。可是在MQTT 3.1.1里面却没有。那么笔者就把MQTT 3.1.1的放在下里吧。读者们可以自行查看。

上面列表里面显示返回码,事实上是主题相关的服务质量要求(Requested QoS)。所以就可以知道他可以会返回四个值。如下

QOS 0:0x00 
QOS 1:0x01 
QOS2 :0x02
Failure :0x80

MQTT主题Topic讲解的更多相关文章

  1. Windows Azure Service Bus (5) 主题(Topic) 使用VS2013开发Service Bus Topic

    <Windows Azure Platform 系列文章目录> 项目文件,请在这里下载 在笔者之前的文章中Windows Azure Service Bus (1) 基础 介绍了Servi ...

  2. MQTT 单片机端讲解

    有空了和大家分享一下,如何从头架构一个高效mqtt并行客户端,基于传统GPRS等较差网络环境和网关等网络环境好的情景(当然仔细讲解mqtt的基本函数使很有必要的).---这会正忙着搬砖 MQTt协议 ...

  3. MQTT协议通俗讲解

    参考 Reference v3.1.1 英文原版 中文翻译版 其他资源 网站 MQTT官方主页 Eclipse Paho 项目主页 测试工具 MQTT Spy(基于JDK) Chrome插件 MQTT ...

  4. RabbitMQ入门(5)——主题(Topic)

    前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...

  5. (转)RabbitMQ学习之主题topic(java)

    http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...

  6. ESA2GJK1DH1K基础篇: STM32+Wi-Fi(AT指令版)实现MQTT源码讲解

    前言 注: 本程序发送心跳包,发送温湿度,返回控制数据这三个发送是单独的,有可能凑到一起发. 由于本身程序就是复杂性的程序,所以这节程序没有使用中断发送,没有使用环形队列发送,为了避免多条消息可能凑到 ...

  7. ESA2GJK1DH1K基础篇: STM32+GPRS(AT指令版)实现MQTT源码讲解(支持Air202,SIM800)

    前言 注: 本程序发送心跳包,发送温湿度,返回控制数据这三个发送是单独的,有可能凑到一起发. 由于本身程序就是复杂性的程序,所以这节程序没有使用中断发送,没有使用环形队列发送,为了避免多条消息可能凑到 ...

  8. C# MQTT M2MQTT

    MQTT 入门介绍 MQTT是基于二进制消息的发布/订阅编程模式的消息协议 实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish).代理(Bro ...

  9. windows环境下apache-apollo服务器搭建及发布订阅测试

    查证了一些资料之后,发现 apache-apollo服务器使用的人还是挺多的,资料也比较齐全,所以直接选择 apache-apollo了,具体性能如何,先用起来再说吧: 1.下载 apache-apo ...

随机推荐

  1. MyBatis--把SQL带进Java

    简单来看软件服务的工作流程:用户端界面操作请求<---->本地处理|远程服务程序拦截转发请求<---->服务端逻辑功能实现<--MyBatis用在这里-->数据库. ...

  2. WooyunWifi路由器

    WooyunWifi 初始化配置 为了开始使用您的WooyunWifi路由器,您需要对WooyunWifi进行初始化配置,这些配置主要位于Openwrt Luci管理界面中,如果您对Openwrt路由 ...

  3. DOS批处理中%~dp0等扩充变量语法详解

    有时候我们看到别人使用%~dp0 ~是扩展的意思,相当于把一个相对路径转换绝对路径%0代指批处理文件自身%1表示批处理文件命令行接收到的第一个参数,%2表示第二个,以此类推%~d0 是指批处理所在的盘 ...

  4. 变分推断到变分自编码器(VAE)

    EM算法 EM算法是含隐变量图模型的常用参数估计方法,通过迭代的方法来最大化边际似然. 带隐变量的贝叶斯网络 给定N 个训练样本D={x(n)},其对数似然函数为: 通过最大化整个训练集的对数边际似然 ...

  5. 次小生成树(LCA倍增)

    算法: 求出MST之后枚举每条在MST之外的边 连上之后会出现环 找到环中除加上的边之外权值最大的边 删除该边之后得到一颗新树 做法: 利用LCA倍增地维护最小生成树上两点之间的最大边权 每次枚举在M ...

  6. 【codevs1690】开关灯 线段树

    这道题需要支持区间修改和区间询问,因此采用线段树加以维护. 由于求的是开着的灯的数目,因此维护sum:区间[ l , r ]中开着的灯的数目. tag取做0/1,表示区间是否反转,在进行标记下传时,如 ...

  7. Nginx动静分离经典案例配置

    随着Nginx高性能Web服务器大量被使用,目前Nginx最新稳定版为1.2.6,张宴兄在实际应用中大量使用Nginx,并分享Nginx高性能Web服务器知识,使得Nginx在国内也是飞速的发展.那今 ...

  8. 【转载】浅析python日志重复输出问题

    出处:https://www.cnblogs.com/huang-yc/p/9209096.html 问题起源: ​ 在学习了python的函数式编程后,又接触到了logging这样一个强大的日志模块 ...

  9. GO 语言队列实现

    队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 队列是一种先进先出的t(First In First Out)的线性表,简称FIFO.允许插入的一端为队尾,允许删除的一 ...

  10. jquery attribute$=value选择器 语法

    jquery attribute$=value选择器 语法 作用:[attribute$=value] 选择器选取每个带有指定属性且以指定字符串结尾的元素. 语法:$("[attribute ...