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字节

原文地址:https://www.cnblogs.com/linzhanfly/p/9936665.html

时间: 2024-10-03 05:47:55

MQTT协议探究(二)的相关文章

MQTT协议探究(三)

1 回顾与本次目标 1.1 回顾 主题通配符 主题语义和用法 WireShark进行抓包分析了报文 报文分析: SUBSCRIBE--订阅主题 SUBACK--订阅确认 UNNSUBSCRIBE--取消订阅 UNSUBACK--取消订阅确认 PUBLISH--发布消息(Qos0,服务质量等级下一节再说吧) 1.2 本节目标 服务质量等级 PUBLISH--发布消息(Qos1 Qos2) PUBACK--发布确认 PUBREC--发布收到 PUBREL--发布释放 PUBCOMP--发布完成 2

MQTT协议(二)

1. 长连接 互联网推送消息主要基于通信双方建立长连接,从而实现实时推送效果.普通的socket连接对服务器的消耗太大,所以出现了类似MQTT这种轻量级.低消耗的协议来维护长连接.维护长连接需要采用心跳机制,客户端发送一个心跳数据包给服务器,服务器返回给客户端一个心跳应答,从而完成一次客户端-服务器握手,这个握手是让双方都知道他们之间的连接是没有断开的.如果超过一个时间阈值,客户端没有收到服务器的心跳应答,或者服务器没有收到客户端的心跳请求,那么表示通信双方连接已经不存在.对客户端来说,则断开与

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

一 复习和目标 1 复习 Nodejs实现WebSocket服务器 Netty实现WebSocket服务器(附带了源码分析) Js api实现WebSocket客户端 注:Nodejs使用的Socket.io模块实现,Netty本身对WebSocket有一定的支持,所以这两种实现都相对容易理解,大家自己可以使用自己喜欢的语言实现(参考Nodejs版本,即不需要考虑过多的情况). 2 目标 使用WebSocket协议进行发送Mqtt消息 即Mqtt协议作为WebSocket协议的子协议进行通信 注

MQTT协议实现Eclipse Paho学习总结二

一.概述 前一篇博客(MQTT协议实现Eclipse Paho学习总结一) 写了一些MQTT协议相关的一些概述和其实现Eclipse Paho的报文类别,同时对心跳包进行了分析.这篇文章,在不涉及MQTT逻辑实现的基础之上分析一下Eclipse Paho中Socket通信的实现,这里我们主要阐述其采用Java同步技术将同步的Socket通信异步化的过程. 二.上菜 先看一下在org.eclipse.paho.client.mqttv3.internal有两个类,CommsSender,Comms

MQTT协议及推送服务(二)

MQTT简介 MQTT全称叫做Message Queuing Telemetry Transport,意为消息队列遥测传输,是IBM开发的一个即时通讯协议.由于其维护一个长连接以轻量级低消耗著称,所以常用于移动端消息推送服务开发. MQTT特性 MQTT具有如下特性: 使用发布/订阅消息模式,提供一对多消息发布: 对负载内容屏蔽的消息传输: 使用TCP/IP进行网络连接: 主流的MQTT是基于TCP进行连接的,同样也有UDP版本的MQTT,但是不太常用,叫做MQTT-SN. 具有三种消息发布服务

物联网MQTT协议分析和开源Mosquitto部署验证

在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定并力推,其具有开放.简单.轻量级以及易于实现的特点使得其即便在资源受限的环境中也能得到很好的使用,比如运行在资源紧缺型的嵌入式系统中或网络带宽非常昂贵的环境中,除此之外,它也被广泛用于遥感勘测.智能家居.能源监测和医疗应用程序等各个领域,是物联网的重要组成部分,将来可能会成为物联网的事实标准. 本篇文章将帮助

MQTT协议简记

 一.定义 MQTT - MQ Telemetry Transport 轻量级的 machine-to-machine 通信协议. publish/subscribe模式. 基于TCP/IP. 支持QoS. 适合于低带宽.不可靠连接.嵌入式设备.CPU内存资源紧张. 是一种比较不错的Android消息推送方案. FacebookMessenger采用了MQTT. MQTT有可能成为物联网的重要协议. MQTT是轻量级基于代理的发布/订阅的消息传输协议,它可以通过很少的代码和带宽和远程设备连接.例

物联网协议测评平台——吊兰使用指南-MQTT协议 Python Paho

在忙了一个周末之后,还是小有成果的.发布了一个简单的物联网平台: http://mqtt.phodal.com,简单地写一下使用指南. CoAP协议 使用Libcoap的话可以用 <code style="box-sizing: border-box; font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; border-top

转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较

一.先看下相关国外的专业数据对四大协议的比较: Protocol                                    CoAP                         XMPP                                                  RESTful HTTP                                                                 MQTT Transport UDP TCP