MQTT控制报文介绍(2)

一、CONNECT –  连接 服务端

        客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文 必须是 CONNECT 报文。在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端 必须将客户端发送的第二个 CONNECT报文当作协议违规处理并断开客户端的连接。

二、MQTT控制报文的结构

三、CONNECT 连接报文

3.1 CONNECT 连接报文固定报头 

3.2 CONNECT 连接报文可变报头 

第1位:

  • 如果清理会话(CleanSession)标志被设置为 0,服务端 必须基于当前会话(使用客户端标识符识别)的状态恢复与客户端的通信。如果没有与这个客户端标识符关联的会话,服务端 必须创建一个新的会话。
  • 如果清理会话(CleanSession)标志被设置为 1,客户端和服务端 必须丢弃之前的任何会话并开始一个新的会话。会话仅持续和网络连接同样长的时间。与这个会话关联的状态数据 不能被任何之后的会话重用。

第二位:

  • 遗嘱标志(Will Flag)被设置为 1,表示如果连接请求被接受了,遗嘱(Will Message)消息 必须被存储在服务端并且与这个网络连接关联。之后网络连接关闭时,服务端 必须发布这个遗嘱消息,除非服务端收到DISCONNECT 报文时删除了这个遗嘱消息 。如果遗嘱标志被设置为 1,连接标志中的 Will QoS 和 Will Retain 字段会被服务端用到,同时有效载荷中必 必须 须包含 Will Topic 和 Will Message 字段 。
  • 如果遗嘱标志被设置为 0,连接标志中的 Will QoS 和 Will Retain 字段 必须设置为 0,并且有效载荷中 不能包含 Will Topic 和 Will Message 字段 。如果遗嘱标志被设置为 0,网络连接断开时, 不能发送遗嘱消息

第三、四位:

  • 如果遗嘱标志被设置为 0,遗嘱 QoS 也 必须设置为 0(0x00)。
  • 如果遗嘱标志被设置为 1,遗嘱 QoS 的值可以等于 0(0x00),1(0x01),2(0x02)。

第五位:

  • 如果遗嘱标志被设置为 0,遗嘱保留(Will Retain)标志也 必须设置为 0 。
  • 如果遗嘱标志被设置为 1:
    • 如果遗嘱保留被设置为 0,服务端 必须将遗嘱消息当作非保留消息发布。
    • 如果遗嘱保留被设置为 1,服务端 必须将遗嘱消息当作保留消息发布 。

第六位:

  • 如果用户名(User Name)标志被设置为 0,有效载荷中 不能包含用户名字段
  • 如果用户名(User Name)标志被设置为 1,有效载荷中 必须包含用户名字段 

第七位:

  • 如果密码(Password)标志被设置为 0,有效载荷中 不能包含密码字段
  • 如果密码(Password)标志被设置为 1,有效载荷中 必须包含密码字段
  • 如果用户名标志被设置为 0,密码标志也 必须设置为 0

        保持连接(Keep Alive)是一个以秒为单位的时间间隔,表示为一个 16 位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端 必须发送一个PINGREQ 报文 。如果保持连接的值非零,并且服务端在一点五倍的保持连接时间内没有收到客户端的控制报文,它 必须断开客户端的网络连接。

非规范 评注:保持连接的实际值是由应用指定的,一般是几分钟。允许的最大值是 18 小时 12 分 15 秒。

3.3 CONNECT 连接报文有效载荷

CONNECT 报文的有效载荷(payload)包含一个或多个以长度为前缀的字段,可变报头中的标志决定是否包含这些字段。如果包含的话, 必须按这个顺序出现:客户端标识符,遗嘱主题,遗嘱消息,用户名,密码

(一)客户端标识符

  • 服务端使用客户端标识符 (ClientId) 识别客户端。连接服务端的每个客户端都有唯一的客户端标识符(ClientId)。客户端和服务端都必须使用 ClientId 识别两者之间的 MQTT 会话相关的状态。
  • 服务端 必须允许 1 到 23 个字节长的 UTF-8 编码的客户端标识符
  • 客户端标识符只能包含这些字符:“0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”(大写字母,小写字母和数字)

(二)遗嘱主题:
        如果遗嘱标志被设置为 1,有效载荷的下一个字段是遗嘱主题。

(三)遗嘱消息:
        如果遗嘱标志被设置为 1,有效载荷的下一个字段是遗嘱消息。遗嘱消息定义了将被发布到遗嘱主题的应用消息。这个字段由一个两字节的长度和遗嘱消息的有效载荷组成,表示为零字节或
多个字节序列。长度给出了跟在后面的数据的字节数,不包含长度字段本身占用的两个字节。

(四)用户名:
        如果用户名(User Name)标志被设置为 1,有效载荷的下一个字段就是它。服务端可以将它用于身份验证和授权。

(五)密码:
        如果密码(Password)标志被设置为 1,有效载荷的下一个字段就是它。密码字段包含一个两字节的长度字段,长度表示二进制数据的字节数(不包含长度字段本身占用的两个字节),后面跟着 0 到 65535 字节的二进制数据。

3.4 CONNECT 报文确认连接请求

四、PUBLISH –  发布消息

PUBLISH 控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息

4.1 PUBLISH报文固定包头

第三位(DUP重发标志):
        如果 DUP 标志被设置为 0,表示这是客户端或服务端第一次请求发送这个 PUBLISH 报文。如果 DUP 标志被设置为 1,表示这可能是一个早前报文请求的重发。客户端或服务端请求重发一个 PUBLISH 报文时, 必须将 DUP 标志设置为 1 。对于 QoS0 的消息,DUP 标志 必须设置为 0 

第一、二位(Qos等级、服务质量 等级):

第 0 位(保留标志):
        如果客户端发给服务端的 PUBLISH 报文的保留(RETAIN)标志被设置为 1,服务端 必须存储这个应用消息和它的服务质量等级(QoS),以便它可以被分发给未来的主题名匹配的订阅者。
        如果客户端发给服务端的 PUBLISH 报文的保留标志位 0,服务端 不能存储这个消息也 不能移除或替换任何现存的保留消息 。

4.2 PUBLISH报文可变报头

可变报头按顺序包含主题名和报文标识符

主题名(Topic Name):用于识别有效载荷数据应该被发布到哪一个信息通道。主题名 必须是 PUBLISH 报文可变报头的第一个字段。

报文标识符:只有当 QoS 等级是 1 或 2 时,报文标识符(Packet Identifier)字段才能出现在 PUBLISH 报文中。

4.3 PIBLISH 报文有效载荷

有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的 PUBLISH 报文是合法的。


五、SUBSCRIBE -  订阅主题

        客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给与那些订阅匹配的主题,服务端发送 PUBLISH 报文给客户端。SUBSCRIBE报文也(为每个订阅)指定了最大的 QoS 等级,服务端根据这个发送应用消息给客户端。

5.1 SUBSCRIBE报文固定报头

5.2 SUBSCRIBE报文可变报头


 

5.3 SUBSCRIBE报文有效载荷

 六、剩余长度值编码

剩余长度 - 简介
位置:固定报头中,从第2个字节开始。
剩余长度等于可变报头的长度(10字节)加上有效载荷的长度。
剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。

示例1:
假设本帧剩余字节为 200,计算剩余长度字段。

  • 使用电脑计算器,将 200 转换为二进制 1100 1000(MSB高位在前)
  • 从右侧低位每7Bit进行一次拆分,依次拆分出:
  • 第1个字节为 100 1000,有进位,高位加上进位1为 1100 1000 = 0xC8 (16进制)。
  • 第2个字节为 1,无进位,为 1 = 0x01 (16进制)。
  • 那么对应的 字节长度的帧格式如下表:

七、 PINGREQ –  心跳请求

客户端发送 PINGREQ 报文给服务端的。用于:
1. 在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
2. 请求服务端发送 响应确认它还活着。
3. 使用网络以确认网络连接没有断开。

相关推荐

  1. MQTT 类型

    2024-03-10 05:46:01       23 阅读
  2. 13 IP层协议-网际控制协议ICMP

    2024-03-10 05:46:01       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-10 05:46:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-10 05:46:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-10 05:46:01       87 阅读
  4. Python语言-面向对象

    2024-03-10 05:46:01       96 阅读

热门阅读

  1. python django StreamingHttpResponse流式响应中文是乱码

    2024-03-10 05:46:01       44 阅读
  2. SpringBoot注解验证参数

    2024-03-10 05:46:01       42 阅读
  3. golang sync.Pool 指针数据覆盖问题

    2024-03-10 05:46:01       43 阅读
  4. yolo-world 源码解析(四)

    2024-03-10 05:46:01       39 阅读
  5. Node.js是什么?

    2024-03-10 05:46:01       46 阅读
  6. 软考笔记--软件架构风格

    2024-03-10 05:46:01       43 阅读
  7. 数据仓库作业一:第1章 绪论

    2024-03-10 05:46:01       36 阅读