MQTT协议探究(二)
1 回顾与本次目标
1.1 回顾
- MQTT控制报文的基本格式
- WireShark进行抓包分析了报文
- 报文分析:
- CONNECT——连接服务器
- CONNACK——确认连接请求
- PINGREQ——心跳请求
- PINGRESP——心跳响应
- DISCONNECT——断开连接
1.2 本节目标
- SUBSCRIBE——订阅主题
- SUBACK——订阅确认
- UNNSUBSCRIBE——取消订阅
- UNSUBACK——取消订阅确认
- PUBLISH——发布消息(Qos0,服务质量等级下一节再说吧)
2 MQTT控制报文格式(补充)
2.1 控制报文的类型
名字 | 值 | 报文流动方向 | 描述 |
---|---|---|---|
SUBSCRIBE | 8 | client -> server | 客户端订阅请求 |
SUBACK | 9 | server -> client | 订阅请求报文确认 |
PUBLISH | 3 | 双向 | 发布消息 |
UNSUBSCRIBE | 10 | client -> server | 取消订阅请求 |
UNSUBACK | 11 | server -> client | 取消订阅报文确认 |
2.2 标识符
控制报文 | 固定报文标志 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|
SUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
SUBACK | Reserved | 0 | 0 | 0 | 0 |
PUBLISH | Used in MQTT 3.1.1 | DUP | QoS | QoS | RETAIN |
UNSUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
UNSUBACK | Reserved | 0 | 0 | 0 | 0 |
- DUP = 控制报文的重复分发标志
- Qos = PUBLISH报文的服务质量等级
- RETAIN = PUBLISH报文是否保留标志
2.3 报文标识符
- 顾名思义就是标识报文的唯一性
- SUBSCRIBE,UNSUBSCRIBE和PUBLISH(QoS大于0)控制报文必须包含一个非零的16位报文标识符(Packet Identifier)。
- Client每次发送一个新的报文时都必须分配一个未使用的报文标识符。
- Client如果进行重发报文必须使用相同的标识符。
- 当Client处理完这个报文对应的确认后,这个报文标识符就释放可重用。
- QoS 1的PUBLISH对应的是PUBACK
- QoS 2的PUBLISH对应的是PUBCOMP
- SUBSCRIBE对应的分别是SUBACK
- UNSUBSCRIBE对应的时UNSUBACK
控制报文 | 报文标识符字段 |
---|---|
SUBSCRIBE | 需要 |
SUBACK | 需要 |
PUBLISH | 需要(如果QoS > 0,Qos=0时不能带) |
UNSUBSCRIBE | 需要 |
UNSUBACK | 需要 |
2.4 有效载荷
控制报文 | 有效载荷 |
---|---|
SUBSCRIBE | 需要 |
SUBACK | 需要 |
PUBLISH | 可选(允许发空负载) |
UNSUBSCRIBE | 需要 |
UNSUBACK | 不需要 |
3 MQTT控制报文示例
3.1 SUBSCRIBE——订阅主题
(1)WireShark抓包获取报文
MQ Telemetry Transport Protocol, Subscribe Request
# 固定报头
Header Flags: 0x82 (Subscribe Request)
1000 .... = Message Type: Subscribe Request (8)
.... 0010 = Reserved: 2
Msg Len: 9
# 可变报头
Message Identifier: 1 # 2个字节,0x0001,报文标识符
# 有效载荷
Topic Length: 4 # 2个字节,0x0004,Topic的长度
Topic: TEST # 2个字节,0x54455354,Topic的值
Requested QoS: At most once delivery (Fire and Forget) (0) # 1个字节 Qos0 0x00
(2)Topic
如果服务端选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求。
Qos为服务质量要求,后面一节讲。
(3)响应
- Server收到Client发送的一个SUBSCRIBE报文时,必须使用SUBACK报文响应
- SUBACK报文必须和等待确认的SUBSCRIBE报文有相同的报文标识符
- 允许Server在发送SUBACK报文之前就开始发送与订阅匹配的PUBLISH报文
- 如果Server收到的SUBSCRIBE报文,Topic与现存的Topic相同,则使用新的订阅(新Qos)替换现存的订阅。
- Client被授权的Qos为0,那么Client发送Qos2将会降级为0。
3.2 SUBACK – 订阅确认
(1)WireShark抓包获取报文
MQ Telemetry Transport Protocol, Subscribe Ack
# 固定报头
Header Flags: 0x90 (Subscribe Ack)
1001 .... = Message Type: Subscribe Ack (9)
.... 0000 = Reserved: 0
Msg Len: 3
# 可变报头
Message Identifier: 1 # 2个字节,0x0001,与SUBSCRIBE相同
# 有效载荷
Granted QoS: At most once delivery (Fire and Forget) (0) # 返回码,最大Qos
(2)返回码
- 0x00 - 成功,最大Qos0
- 0x01 - 成功,最大Qos1
- 0x02 - 成功,最大Qos2
- 0x80 - 失败
3.3 PUBLISH – 发布消息(Qos0)
(1)WireShark抓包获取报文
MQ Telemetry Transport Protocol, Publish Message
# 固定报头
Header Flags: 0x30 (Publish Message)
0011 .... = Message Type: Publish Message (3) # 代表发布消息
.... 0... = DUP Flag: Not set # 重发标志
.... .00. = QoS Level: At most once delivery (Fire and Forget) (0) # Qos
.... ...0 = Retain: Not set # 保留标志
Msg Len: 16
# 可变报头
### 主题名
Topic Length: 4 # 2个字节,0x0004
Topic: TEST # 4个字节
### 报文标识符,当Qos不为0时,必须带上。
# 有效载荷
Message: HelloWorld
(2)固定报头
重发标志:DUP为0,代表Client第一次发这个报文;DUP为1,代表Client重发已发的报文。对于Qos为0时,DUP必须为0。
服务质量等级
Qos | Bit2 | Bit1 | 描述 |
---|---|---|---|
0 | 0 | 0 | 最大分发一次 |
1 | 0 | 1 | 至少一次 |
2 | 1 | 0 | 只分发一次 |
- | 1 | 1 | 保留位 |
(3)保留标志(RETAIN)
- Client发送给Server报文的RETAIN为0,Server不能存储这个消息,也不能移除或替换任何现存的消息。
- Client发送给Server报文的RETAIN为1,Server必须存储该消息和Qos,以便分发给未来的主题名匹配的订阅者。(如果有新的订阅,Server存在最近保留的消息,它将发送保留消息给新的Client。并且Server发送的该消息必须将RETAIN设为0.)
- Server不保留零字节(有效载荷)的保留消息。
- Client发送给Server报文的RETAIN为1,Qos为0,Server必须丢弃之前为那个Topic保留的任何消息,并保留该消息,但是该消息也是可以被丢弃的。
(4)响应
服务质量等级 | 预期响应 |
---|---|
Qos0 | 无响应 |
Qos1 | PUBACK报文 |
Qos2 | PUBREC报文 |
(5)动作
- 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重复,因此发布的消息可能会匹配多个过滤器,所以服务端必须将消息分发给所有订阅匹配的QoS等级最高的客户端。
3.4 UNSUBSCRIBE –取消订阅
(1)WireShark抓包获取报文
MQ Telemetry Transport Protocol, Unsubscribe Request
# 固定报头
Header Flags: 0xa2 (Unsubscribe Request)
1010 .... = Message Type: Unsubscribe Request (10)
.... 0010 = Reserved: 2
Msg Len: 8
# 可变报头
Message Identifier: 2 # 报文标识符,0x0002
# 有效载荷
Topic Length: 4
Topic: TEST
(2)响应
- UNSUBSCRIBE报文提供的主题过滤器(无论是否包含通配符)必须与服务端持有的这个客户端的当前主题过滤器集合逐个字符比较。如果有任何过滤器完全匹配,那么它(Server)自己的订阅将被删除,否则直接返回SUBACK响应。
- Server删除了一个订阅:
- 必须停止分发任何新消息给该Client
- 必须完成分发任何已经开始发往Client发送的QoS 1和QoS 2的消息
- 可以继续发送任何现存的准备分发给客户端的缓存消息
- 即使Server没有删除任何订阅消息,服务器也需要发送一个SUBACK响应。
- 如果服务端收到包含多个主题过滤器的UNSUBSCRIBE报文,它必须如同收到了一系列的多个UNSUBSCRIBE报文一样处理那个报文,除了将它们的响应合并到一个单独的UNSUBACK报文外。(这句话有疑惑??)
3.5 UNSUBACK – 取消订阅确认
(1)WireShark抓包获取报文
MQ Telemetry Transport Protocol, Unsubscribe Ack
Header Flags: 0xb0 (Unsubscribe Ack)
1011 .... = Message Type: Unsubscribe Ack (11)
.... 0000 = Reserved: 0
Msg Len: 2
Message Identifier: 2
4 订阅的主题名与主题过滤器
4.1 主题通配符
- 主题分割符号:/
- 主题多层通配符:#,必须在最后面且只有一个
- sport/tennis/#/ranking 无效
- sport/tennis#" 无效
- 主题单层通配符:+,可以有多个
- sport+ 无效
# demo1:多层通配符
订阅:"sport/tennis/player1/#"
收到:sport/tennis/player1
sport/tennis/player1/ranking
sport/tennis/player1/score/wimbledon
# demo2: 单层通配符
订阅:"sport/+"
收到: sport/tennis
收不到: sport
sport/
# demo3:单层通配符
订阅:"+"
收到: sport
收不到: sport/
# demo4:单层通配符
订阅:"+/"
收到: sport/
收不到: sport
4.2 以$开头的主题(非绝对)
- $通常预留给服务器使用(非绝对,具体看服务器的配置)
- $SYS/ 被广泛用作包含服务器特定信息或控制接口的主题的前缀
- 订阅”#“不会收到”$“开头的主题消息
- +/monitor/Clients不会收到的客户端不会收到任何发布到 “$SYS/monitor/Clients” 的消息
4.3 主题语义和用法
- 只包含斜杠 “/” 的主题名或主题过滤器是合法的
- 主题名和主题过滤器可以包含空格
- 主题名和主题过滤器是区分大小写的
- 主题名或主题过滤器以前置或后置斜杠 “/” 区分
- 主题名和主题过滤器不能包含空字符(Unicode U+0000)
- 主题名和主题过滤器不能只有空格符
- 主题名和主题过滤器是UTF-8编码字符串,它们不能超过65535字节
MQTT协议探究(二)的更多相关文章
- MQTT协议探究(一)
1 准备阶段 MQTT客户端:https://www.cnblogs.com/linzhanfly/p/9923577.html WireShark MQTT服务器(iot.eclipse.org) ...
- MQTT协议探究(三)
1 回顾与本次目标 1.1 回顾 主题通配符 主题语义和用法 WireShark进行抓包分析了报文 报文分析: SUBSCRIBE--订阅主题 SUBACK--订阅确认 UNNSUBSCRIBE--取 ...
- WebSocket协议探究(三):MQTT子协议
一 复习和目标 1 复习 Nodejs实现WebSocket服务器 Netty实现WebSocket服务器(附带了源码分析) Js api实现WebSocket客户端 注:Nodejs使用的Socke ...
- WebSocket协议探究(序章)
一 WebSocket协议基于HTTP和TCP协议 与往常一样,进入WebSocket协议学习之前,先进行WebSocket协议抓包,来一个第一印象. WebSocket能实现客户端和服务器间双向.基 ...
- Android消息推送(二)--基于MQTT协议实现的推送功能
国内的Android设备,不能稳定的使用Google GCM(Google Cloud Messageing)消息推送服务. 1. 国内的Android设备,基本上从操作系统底层开始就去掉了Googl ...
- MQTT协议实现Eclipse Paho学习总结二
一.概述 前一篇博客(MQTT协议实现Eclipse Paho学习总结一) 写了一些MQTT协议相关的一些概述和其实现Eclipse Paho的报文类别,同时对心跳包进行了分析.这篇文章,在不涉及MQ ...
- MQTT协议及推送服务(二)
MQTT简介 MQTT全称叫做Message Queuing Telemetry Transport,意为消息队列遥测传输,是IBM开发的一个即时通讯协议.由于其维护一个长连接以轻量级低消耗著称,所以 ...
- 海鑫智圣:物联网漫谈之MQTT协议
什么是MQTT协议 MQTT(消息队列遥测传输协议)是IBM在1999年专门针对物联网等应用场景来制订的轻量级双向消息传输协议,它主要是为了解决物联网上使用到的设备的互相通信的问题,以及这些设备与后端 ...
- 基于MQTT协议进行应用开发
官方协议有句如下的话来形容MQTT的设计思想: "It is designed for connections with remote locations where a "sma ...
随机推荐
- JMeter压力测试及并发量计算-2
一个每天1000万PV的网站需要什么样的性能去支撑呢?继续上一篇,下面我们就来计算一下,前面我们已经搞到了一票数据,但是这些数据的意义还没有说.技术是为业务服务的,下面就来说说怎么让些数据变得有意义. ...
- Linux ubuntu centos 下 grep显示前后几行信息
标准unix/linux下的grep通过下面参数控制上下文 grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行grep -B 5 foo file 显示foo及前5 ...
- Xshell登录Vagrant方式
Xshell登录Vagrant方式 我上一篇文章 介绍了vagrant 如何创建虚拟机集群,在上篇文章的基础上,用xshell 登录 虚拟机发现 默认是无法使用账号密码登录root账号,只能使用vag ...
- 【Java/MySql】使用JDBC访问MySql数据库的Maven工程
下载链接:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-1.rar pom.xml里写: <p ...
- ZT:阿里合伙人发文:十年磨一剑,自研数据库终拿世界第一
按:真正做技术的,就该这样. 以下为全文转载 (观察者网讯) 10月24日,阿里巴巴合伙人.高德总裁刘振飞在阿里云开发者社区发文,回忆从2009年启动“去IOE”工程到2019年OceanBase拿下 ...
- 数据分析 - Excel 配色, 绘图, 技巧
美学 配色 画图本身是美学的展示, 出色的配色是必须的 虽然本身美学并不是数据分析的必要, 但是也不能太low 如果做的太丑展示也是很尴尬 配色网站 点击这里 配置 现版本的 excel 中已存在较为 ...
- c++ template Queue
#pragma once#include <iostream>#include <iomanip> using namespace std; template<class ...
- Redis有序Set、无序Set的使用经历
为了实现一个类似关系数据库中的卖家信息的单表,首先我们知道单表必然可增删查改,其次为了区分先来后到又需要有ID主键且自增长.开始考虑使用hash数据类型,因为hash是key+列1.列2...这样一来 ...
- 通过命令行方式连接redis
1.首先安装redis客户端 yum install redis 2.连接 redis-cli -h host -p port -a password host:远程redis服务器host port ...
- for 和 while 用于遍历时候的区别
for: 以空格作为间隔符,输出字段. read: 以行作为间隔符,输出字段. 对于文件来说,如果只有一列,for 和 read 无区别, 多列的话, 有区别. read 用法详情: 见 如下转 ...