1 回顾与本次目标

1.1 回顾

  • 主题通配符
  • 主题语义和用法
  • WireShark进行抓包分析了报文
  • 报文分析:
    • SUBSCRIBE——订阅主题
    • SUBACK——订阅确认
    • UNNSUBSCRIBE——取消订阅
    • UNSUBACK——取消订阅确认
    • PUBLISH——发布消息(Qos0,服务质量等级下一节再说吧)

1.2 本节目标

  • 服务质量等级
  • PUBLISH——发布消息(Qos1 Qos2)
  • PUBACK——发布确认
  • PUBREC——发布收到
  • PUBREL——发布释放
  • PUBCOMP——发布完成

2 MQTT控制报文格式(补充)

2.1 控制报文的类型

名字 报文流动方向 描述
PUBLISH 3 双向 发布消息
PUBACK 4 双向 QoS 1消息发布收到确认
PUBREC 5 双向 QoS 2发布收到(保证交付第一步)
PUBREL 6 双向 QoS 2发布释放(保证交付第二步)
PUBCOMP 7 双向 QoS 2消息发布完成(保证交互第三步)

2.2 标识符

控制报文 固定报文标志 Bit 3 Bit 2 Bit 1 Bit 0
PUBLISH Used in MQTT 3.1.1 DUP QoS QoS RETAIN
PUBACK Reserved 0 0 0 0
PUBREC Reserved 0 0 0 0
PUBREL Reserved 0 0 1 0
PUBCOMP Reserved 0 0 0 0
  • DUP = 控制报文的重复分发标志
  • Qos = PUBLISH报文的服务质量等级
  • RETAIN = PUBLISH报文是否保留标志

2.3 报文标识符

  • Client每次发送一个新的报文时都必须分配一个未使用的报文标识符。
  • Client如果进行重发报文必须使用相同的标识符。
  • 当Client处理完这个报文对应的确认后,这个报文标识符就释放可重用。
    • QoS 1的PUBLISH对应的是PUBACK
    • QoS 2的PUBLISH对应的是PUBCOMP
控制报文 报文标识符字段
PUBLISH 需要(如果QoS > 0,Qos=0时不能带)
PUBACK 需要
PUBREC 需要
PUBREL 需要
PUBCOMP 需要

2.4 有效载荷

控制报文 有效载荷
PUBLISH 可选(允许发空负载)
PUBACK 不需要
PUBREC 不需要
PUBREL 不需要
PUBCOMP 不需要

3 服务质量等级和协议流程

3.1 概述

  • 分发协议是对称的,客户端和服务端既可以是发送者也可以是接收者。
  • 分发协议关注的是从单个发送者单个接收者的应用消息。
  • 服务端分发应用消息给多个客户端时,每个客户端独立处理。
  • 分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。

3.2 QoS 0:最多分发一次

  • 接收者不会发送响应(无需确认送达),发送者也不会重试(DUP=0)
  • 发送者必须发送QoS=0,DUP=0的PUBLISH报文
  • 协议流程:
发送者 方向 接收者
PUBLISH报文 Qos=0 DUP=0
------------------->
分发应用消息给适当的后续接收者(们)

3.3 QoS 1: 至少分发一次

  • QoS 1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK报文(带上报文标识符)确认。
  • 发送者
    • 新消息都必须分配一个未使用的报文标识符(收到PUBACK时,该报文标识符可以重用)。
    • 发送的PUBLISH报文必须包含报文标识符且QoS=1,DUP=0(不重发)。
    • 必须将这个PUBLISH报文看作是未确认的 ,直到从接收者那收到对应的PUBACK报文。
  • 接收者
    • 响应的PUBACK报文必须包含一个报文标识符 ,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
    • 发送了PUBACK报文之后,接收者必须将任何包含相同报文标识符的入站PUBLISH报文当作一个新的消息,并忽略它的DUP标志的值。
  • 协议流程:
发送者 方向 接收者
存储消息
PUBLISH报文 QoS=1, DUP=0 报文标识符 ------------------->
开始应用消息的后续分发
<------------------- PUBACK报文,带报文标识符
丢弃消息

3.4 QoS 2: 仅分发一次

  • 消息丢失和重复都是不可接受的

  • 消息可变报头中有报文标识符

  • 发送者

    • 新消息都必须分配一个未使用的报文标识符(收到PUBCOMP时,该报文标识符可以重用)。
    • PUBLISH报文必须包含报文标识符且报文的QoS=2,,DUP=0。
    • 必须将这个PUBLISH报文看作是未确认的 ,直到从接收者那收到对应的PUBREC报文。
    • 收到PUBREC报文后必须发送一个PUBREL报文(报文标识符)。
    • 必须将这个PUBREL报文看作是 未确认的 ,直到从接收者那收到对应的PUBCOMP报文。
    • 一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。
  • 接收者

    • 响应的PUBREC PUBREL PUBCOMP报文必须包含相同的报文标识符
  • 协议流程图:Client -> Server

发送者 方向 接收者
存储消息
发送PUBLISH报文,Qos2,DUP=0,带报文标识符
->
方法A:存储消息
方法B:存储报文标识符,开始向前分发这个应用消息
发送PUBREC报文,带报文标识符
<-
丢弃消息,存储PUBREC中的报文标识符
发送PUBREL报文,带报文标识符
->
方法A:开始向前分发应用消息并丢弃
方法B:丢弃报文标识符
发送PUBCOMP报文,带报文标识符
<-
丢弃已保存的报文标识符
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:Make message available
PUBCOMP <----- Message ID = x

4 MQTT控制报文示例

4.1 PUBLISH – 发布消息

(1)WireShark抓包获取报文

# Qos1
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x32 (Publish Message)
0011 .... = Message Type: Publish Message (3)
.... 0... = DUP Flag: Not set
.... .01. = QoS Level: At least once delivery (Acknowledged deliver) (1)
.... ...0 = Retain: Not set
Msg Len: 18
Topic Length: 4 # 0x0004
Topic: TEST
Message Identifier: 1 # 0x0001,报文标识符
Message: HelloWorld # 18 - 2 - 4 - 2 = 10个字节 # Qos2
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x34 (Publish Message)
0011 .... = Message Type: Publish Message (3)
.... 0... = DUP Flag: Not set
.... .10. = QoS Level: Exactly once delivery (Assured Delivery) (2)
.... ...0 = Retain: Not set
Msg Len: 18
Topic Length: 4
Topic: TEST
Message Identifier: 2

(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)响应

服务质量等级 预期响应
Qos0 无响应
Qos1 PUBACK报文
Qos2 PUBREC报文

4.2 PUBACK –发布确认

(1)WireShark抓包获取报文

MQ Telemetry Transport Protocol, Publish Ack
Header Flags: 0x40 (Publish Ack)
0100 .... = Message Type: Publish Ack (4)
.... 0000 = Reserved: 0
Msg Len: 2
Message Identifier: 1 # 报文标识符

(2)概述

  • PUBACK报文只需要表明接收者收到了某条PUBLISH报文即可。
  • Client设置CleanSession=0重连时,Client和Server必须使用原始的报文标识符重发未确认的PUBLISH报文。
  • 因为存在重发和报文标志符的复用(Receiver返回PUBACK后,即使有相同的报文标识符,也认为是新的PUBLISH报文),所以可能存在转发超过一次(Qos1只保证至少1次)的情况。

4.3 PUBREC – 发布收到(QoS 2,第一步)

(1)WireShark抓包获取报文

MQ Telemetry Transport Protocol, Publish Received
Header Flags: 0x50 (Publish Received)
0101 .... = Message Type: Publish Received (5)
.... 0000 = Reserved: 0
Msg Len: 2
Message Identifier: 2

(2)概述

  • 3.4节提到Reciver收到Qos2的PUBLISH报文后,可以有两种处理方式

    • A:存储消息
    • B:存储报文标识符(不再分发相同报文标识符的PUBLISH报文),开始分发这个应用消息
  • PUBREC报文是为了告诉Sender收到了消息
  • 其实PUBREC与PUBACK作用相同,表示Receiver已收到消息,所以可以把存储在Sender的消息删除(消息的所有权转让)

4.4 PUBREL – 发布释放

(1)WireShark抓包获取报文

MQ Telemetry Transport Protocol, Publish Release
Header Flags: 0x62 (Publish Release)
0110 .... = Message Type: Publish Release (6)
.... 0010 = Reserved: 2
Msg Len: 2
Message Identifier: 2

(2)概述

  • Sender收到PUBREC之前,Sender仍然可能在发送相同报文标识符的PUBLISH报文,所以收到PUBREC之后需要把报文标识符记录下来(不再发送该报文标识符的PUBLISH报文)。
  • Sender发送PUBREL报文是为了通知Receiver,可以开始接收相同报文标识符的PUBLISH报文了(报文标识符的复用)。
  • 但Sender在没有收到响应(PUBCOMP)之前,仍然不会去发送相同报文标识符的PUBLISH报文。

4.5 PUBCOMP – 发布完成

(1)WireShark抓包获取报文

MQ Telemetry Transport Protocol, Publish Complete
Header Flags: 0x70 (Publish Complete)
0111 .... = Message Type: Publish Complete (7)
.... 0000 = Reserved: 0
Msg Len: 2
Message Identifier: 2

(2)概述

  • Receiver收到了PUBREL报文

    • A:开始分发消息并丢弃
    • B:丢弃报文标识符(可以接收相同报文标识符的PUBLISH报文)
  • 发送PUBCOMP告知Sender,可以发送相同报文标识符的PUBLISH报文了。

MQTT协议探究(三)的更多相关文章

  1. MQTT协议探究(一)

    1 准备阶段 MQTT客户端:https://www.cnblogs.com/linzhanfly/p/9923577.html WireShark MQTT服务器(iot.eclipse.org) ...

  2. MQTT协议探究(二)

    1 回顾与本次目标 1.1 回顾 MQTT控制报文的基本格式 WireShark进行抓包分析了报文 报文分析: CONNECT--连接服务器 CONNACK--确认连接请求 PINGREQ--心跳请求 ...

  3. WebSocket协议探究(三):MQTT子协议

    一 复习和目标 1 复习 Nodejs实现WebSocket服务器 Netty实现WebSocket服务器(附带了源码分析) Js api实现WebSocket客户端 注:Nodejs使用的Socke ...

  4. WebSocket协议探究(序章)

    一 WebSocket协议基于HTTP和TCP协议 与往常一样,进入WebSocket协议学习之前,先进行WebSocket协议抓包,来一个第一印象. WebSocket能实现客户端和服务器间双向.基 ...

  5. 采用MQTT协议实现android消息推送(1)MQTT 协议简介

    1.资料 mqtt官网 http://mqtt.org/ 服务端程序列表 https://github.com/mqtt/mqtt.github.io/wiki/servers 客户端库列表 http ...

  6. 海鑫智圣:物联网漫谈之MQTT协议

    什么是MQTT协议 MQTT(消息队列遥测传输协议)是IBM在1999年专门针对物联网等应用场景来制订的轻量级双向消息传输协议,它主要是为了解决物联网上使用到的设备的互相通信的问题,以及这些设备与后端 ...

  7. 基于MQTT协议进行应用开发

    官方协议有句如下的话来形容MQTT的设计思想: "It is designed for connections with remote locations where a "sma ...

  8. 云巴:基于MQTT协议的实时通信编程模型

    概要 有人常问,云巴实时通信系统到底提供了一种怎样的服务,与其他提供推送或 IM 服务的厂商有何本质区别.其实,从技术角度分析,云巴与其它同类厂商都是面向开发者的通信服务,宏观的编程模型都是大同小异, ...

  9. MQTT协议(一)

    MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约.轻量,易于使用,针对受限环境(带宽低.网络延迟高.网络通信不稳定),可以简单 ...

随机推荐

  1. Memcached与Memcache区别

    在写这篇文章之前一直对memcache .memcached模糊,相差一个字母,特此总结下: Memcache是什么? Memcache是一个自由和开放源代码.高性能.分配的内存对象缓存系统.用于加速 ...

  2. 性能分析 | Java服务器内存过高&CPU过高问题排查

    一.内存过高 1.内存过高一般有两种情况:内存溢出和内存泄漏 (1)内存溢出:程序分配的内存超出物理机的内存大小,导致无法继续分配内存,出现OOM报错 (2)内存泄漏:不再使用的对象一直占据着内存不释 ...

  3. mac安装mysql数据库及配置环境变量

    mac安装mysql数据库及配置环境变量 mac安装mysql数据库及配置环境变量 原文文链接:https://blog.csdn.net/qq_36004521/article/details/80 ...

  4. linux中如何配置vim的别名为vi?

    答: 向~/.bashrc中添加如下内容: alias vi=vim

  5. leetcode 79. Word Search 、212. Word Search II

    https://www.cnblogs.com/grandyang/p/4332313.html 在一个矩阵中能不能找到string的一条路径 这个题使用的是dfs.但这个题与number of is ...

  6. js for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解?

    js的问题for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解? 很奇怪的一个for循环 竟然是将原来数组的数据全改为0

  7. kotlin标准委托之惰性装载

    lazy函数,接受一个lambda表达式作为参数,返回一个Lazy<T> 类型的实例,这个实例可以作为委托,实现惰性加载属性;第一次调用get时,将会执行从lazy函数传入的lambda表 ...

  8. php中如何传递Session ID

    一般通过在各个页面之间传递的唯一的 Session ID,并通过 Session ID 提取这个用户在服务器中保存的 Session 变量,来跟踪一个用户.常见的 Session ID 传送方法主要有 ...

  9. 免费的HTML5版uploadify

    转http://www.cnblogs.com/lvdabao/p/3452858.html var defaults = { fileTypeExts:'',//允许上传的文件类型,格式'*.jpg ...

  10. Jmeter之分布式部署测试

    在使用Jmeter进行性能测试时,因受单机电脑的配置限制,可能无法支持较大数量的并发,此时就需要使用Jmeter提供的分布式测试的功能. jmeter分布式测试的执行原理是选择一台作为调度机,其他机器 ...