zoukankan      html  css  js  c++  java
  • MQTT协议探究(三)

    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报文了。
  • 相关阅读:
    JavaScript 数组
    Function类型
    javascript面向对象(一)
    javascript变量的作用域
    登陆验证
    注册验证
    php类
    二叉搜索树的 查询最小值
    二叉 搜索树查找最大值
    二叉搜索树 中查找是否存在该值
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/9952966.html
Copyright © 2011-2022 走看看