zoukankan      html  css  js  c++  java
  • MQTT协议笔记之发布流程

    MQTT协议笔记之发布流程

    前言

    这次要讲到客户端/服务器的发布消息行为,与PUBLISH相关的消息类型,会在这里看到。

    PUBLISH

    客户端发布消息经由服务器分发到所有对应的订阅者那里。一个订阅者可以订阅若干个主题(Topic name),但一个PUBLISH消息只能拥有一个主题。

    消息架构一览:

     Description76543210
    Fixed header/固定头部
    byte 1   Message Type(3) DUP flag QoS level RETAIN
        0 0 1 1 0 0 1 0
    byte 2 Remaining Length
    Variable header/可变头部
    Topic name
    byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Length LSB (3) 0 0 0 0 0 0 1 1
    byte 3 'a' (0x61) 0 1 1 0 0 0 0 1
    byte 4 '/' (0x2F) 0 0 1 0 1 1 1 1
    byte 5 'b' (0x62) 0 1 1 0 0 0 1 0
    Message Identifier
    byte 6 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 7 Message ID LSB (10) 0 0 0 0 1 0 1 0
    Playload/消息体
    BLOB,二进制对象形式。二进制具体包含的内容和格式,可有应用程序自身定义。若消息体为空(0长度)也是可能的。

    固定头部

    DUP flag,设为0,表示当前为第一次发送。

    RETAIN flag,只有在PUBLISH消息中才有效。

    • 1:表示发送的消息需要一直持久保存,不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。 备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送,不是所有。
    • 0:仅仅为当前订阅者推送此消息。

    可变头部

    Topic name,UTF-8编码字符串形式,不支持通配符!

    消息体

    一般作为UTF-8编码写入接口,但不排除自定义的消息格式。

    空的消息体(zero-length)的PUBLISH消息也可以是合法的。

    当服务器接收到空消息体(zero-length payload)、retain = 1、具有topic name的一个PUBLISH特殊消息,表示同时满足retain = 1、相同topic name的这两个特征的被持久化PUBLISH消息,可被删除。

    Response/响应

    固定头部QoS level决定了消息中间件针对发布者具体需要响应的内容:

    QoS Level Expected response
    QoS 0 None
    QoS 1 PUBACK
    QoS 2 PUBREC

    备注:仅仅针对发布PUBLISH消息的发布者。

    Actions:

    无论是订阅者还是服务器接收到PUBLISH消息之后,需要根据QoS level执行不同动作。

    QoS Level Expected Action
    QoS 0 发送到所有感兴趣者
    QoS 1 持久化记录下来,发送到所有感兴趣的参与者,返回一个PUBACK消息给发送者
    QoS 2 持久化记录下来,暂时不发送所有感兴趣的参与者,返回一个PUBREC消息给发送者

    如果服务器收到PUBLISH消息,参与者指的是订阅者。如果订阅者收到PUBLISH消息,参与者就是服务器。 需要注意:

    1. 发布者发布的PUBLISH消息发送到服务器,在payload/消息体处可能夹带有私货,可能含有自定义的数据 格式
    2. 若兼容MQTT客户端,经由服务器分发到所有对应订阅者处只能是规规矩矩的PUBLISH消息,并且固定头部的RETAIN标志不能被设置成有效值1

    授权

    未经授权的发布者提交的PUBLISH消息,服务器会忽略掉,客户端不会被通知。

    PUBACK

    作为订阅者/服务器接收(QoS level = 1)PUBLISH消息之后对发送者的响应,整个消息不复杂。

     Description76543210
    Fixed header/固定头部
    byte 1   Message type (4) DUP flag QoS flags RETAIN
        0 1 0 0 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可变头部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    虽没有消息体,但可变头部附加一个16位的无符号short类型。

    PUBREC

    字面意思为Assured publish received,作为订阅者/服务器对QoS level = 2的发布PUBLISH消息的发送方的响应,确认已经收到,为QoS level = 2消息流的第二个消息。 和PUBACK相比,除了消息类型不同外,其它都是一样。

     Description76543210
    Fixed header/固定头部
    byte 1   Message type (5) DUP flag QoS flags RETAIN
        0 1 0 1 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可变头部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    无论是订阅者还是服务器,在消费PUBREC消息之后需要发送一个PUBREL消息给发送者(和PUBREC具有同样的消息ID),确认已收到。

    PUBREL

    Qos level = 2的协议流的第三个消息,有PUBLISH消息的发布者发送,参与方接收。完整示范如下:

     Description76543210
    Fixed header/固定头部
    byte 1   Message type (6) DUP flag QoS flags RETAIN
        0 1 1 0 0 0 1 x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可变头部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    QoS level 1,PUBREL消息要求如此。

    DUP flag 为0,表示消息第一次被发送。

    毫无疑问,剩余长度为2个byte长度。

    可变头部中,消息ID和发布者接收到的PUBREC所包含的消息ID是一致的。

    动作:

    1. 服务器接收到发布者(a)的PUBREL消息,此时服务器让发布者(a)刚才发布PUBLISH消息可用,发送此PUBLISH消息给所有订阅此主题的订阅者,然后发送PUBCOMP消息给发布者(a)
    2. 可变头部包含消息ID和服务器接收的PUBREL消息ID是一致的。 一个订阅者接收到PUBREL消息,订阅者使PUBLISH消息可用,然后反馈一个PUBCOMP消息给服务器

    PUBCOMP

    作为QoS level = 2消息流第四个,也是最后一个消息,由收到PUBREL的一方向另一方做出的响应消息。

    完整的消息一览,和PUBREL一致,除了消息类型。

     Description76543210
    Fixed header/固定头部
    byte 1   Message type (7) DUP flag QoS flags RETAIN
        0 1 1 1 x x x x
    byte 2   Remaining Length (2)
        0 0 0 0 0 0 1 0
    Variable header/可变头部
    Message Identifier
    byte 1 Message ID MSB (0) 0 0 0 0 0 0 0 0
    byte 2 Message ID LSB (10) 0 0 0 0 1 0 1 0

    当客户端接收一个PUBCOMP消息时,客户端摒弃原来的消息,因为它已经成功发送消息到服务器。

    小结

    消息的发布和确认等一些流程,主要是跟消息发布者所设定的QoS level有关;稍加整理,绘制了下面一张图,理解起来可能会更清晰些:

    Publish流程图

    上图针对的是客户端发布消息到服务器端的方向。

    为了确保消息已经成功传递过去,只有收到了确认,才会让人特别放心。

    在QoS level = 2时,通信双方都需要知道各自的确认流程以及所处阶段等,交互很多,数据量大的情况下,可能会造成数据线路传递拥塞。服务器选择QoS = 0/1,大部分情况都是可以应对的。 比如重要消息,就要确保对方都要收到,然后彼此确认,OK,这个消息是真实、有效的。

    无论Qos level为0、1,还是2,服务器(具备所有条件都满足之后)总要把收到的具体内容和topic组装成一个新的PUBLISH Message(也不一定要重新构造,但要求推送的PUBLISH消息,一定要具有明确的主题和内容,RETAIN标志不能设置为1)推送到所有感兴趣的订阅者。

    嗯,消息的发布来源别忘记还有可能来自CONNECT消息中的Will Topic和Will Message,若是设置了Will flag标记的话。

    原文 http://www.blogjava.net/yongboy/archive/2014/02/10/409689.html

  • 相关阅读:
    使用Random类生成指定范围的随机数
    js ==和===的区别
    js中的undefined
    js的split函数
    springboot发送邮件
    1032 Sharing (25分)(数组链表)
    1031 Hello World for U (20分)
    1030 Travel Plan (30分)(dijkstra 具有多种决定因素)
    1029 Median (25分)
    1026 Table Tennis (30分)
  • 原文地址:https://www.cnblogs.com/yudar/p/4642375.html
Copyright © 2011-2022 走看看