您的当前位置:首页正文

【IM即时通讯】MQTT协议的详解(2)- CONNECT Packet

2024-12-01 来源:个人技术集锦

【IM即时通讯】MQTT协议的详解(2)- CONNECT Packet



前言

关于所有的类型的数据示例已经在上面一篇博客说完:
回顾的同学可以直达这里

说明

CONNECT Packet此包是客户端与服务端建立连接后,发送的第一个包,且第一个包必须是此包。在一个连接中,该包只能发送一次。若发送了多次,当服务器第二次收到该包时,应该作为违法处理,立即断开连接。


一、固定同步详解、可变头部详解

  • 固定头部
+---------------------------------------------------------+
|   bit   |  7  |  6  | 5   |  4  |  3  |  2  |  1  |  0  |
+---------------------------------------------------------+
|  byte1  |  0  |  0  | 0   |  1  |  0  |  0  |  0  |  0  |
+---------------------------------------------------------+
| byte2...|              Remaining Length                 |
+---------------------------------------------------------+
  • 可变头部
+--------+----------------+---+---+---+---+---+---+---+---+
|  Bit   |   Description  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------------------------------------------------+
| byte 1 |  Length MSB (0)| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---------------------------------------------------------+
| byte 2 |  Length LSB (4)| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---------------------------------------------------------+
| byte 3 |       'M'      | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
+---------------------------------------------------------+
| byte 4 |       'Q'      | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
+---------------------------------------------------------+
| byte 5 |       'T'      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
+---------------------------------------------------------+
| byte 6 |       'T'      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
+---------------------------------------------------------+
| byte 7 |     Level(4)   | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---------------------------------------------------------+
| byte 8 |        x       | x | x | x | x | x | x | x | 0 |
+--------+----------------+---+---+---+---+---+---+---+---+
| byte 9 |                 Keep Alive MSB                 |
+---------------------------------------------------------+
| byte 10|                 Keep Alive LSB                 |
+--------+----------------+---+---+---+---+---+---+---+---+

其中,

  • 如前面介绍,前 2 个字节是包 ID。
  • 3 ~ 6 字节是协议名称,字符使用 UTF-8 编码;
  • 第 7 个字节是协议等级(协议版本。3.1.1 版本对应的协议等级是 4
  • 第8个字节包含一些连接标记位。如下图所示:
BitDescription
7是否有用户名字标志位英文:【User Name Flag】
6是否有密码标志位 英文:【Password Flag】
5决定遗嘱消息是否被服务器保留英文:【Will Retain】
4~3决定遗嘱消息的服务质量等级 英文:【Will QoS】
2指示是否有遗嘱消息需要在连接断开时发布 英文:【Will Flag】
1决定是否清除之前的会话信息 英文:【Clear session】
0保留位,必须设置为0 (也有可能不为0)英文:【Reserved】

注意

若服务端不支持客户端协议版本,需要响应一个 CONNACK 包,指定 code 为 0x01,然后断开连接.服务端需校验 Reserved 位。若值不为 0,需断开连接。

  • Clear session:用来指定对 Session 的处理方式。若值为0,在服务端和客户端断开连接后,它们都要保存 Session 信息,以便再次连上时恢复之前 Session 中的信息。除此之外,服务端还需要在断开连接后保存 QoS 1 和 QoS 2 消息和客户端的订阅内容;若值为1,当客户端和服务端连接上时,必须丢弃之前的 Session 状态信息再创建一个新的 Session 和订阅内容。

    • 位置:连接标识字节的第1位(Bit 1)

    • 在客户端,Session 状态信息包括:
      已被发送到服务端,但还没有被确认的 QoS 1 和 QoS 2 消息;
      已被服务器接收,但还没有被确认的 QoS 2 消息。
      在服务端,Session 状态信息包括:

    • 客户端的订阅内容;
      已被发送到服务端,但还没有被确认的 QoS 1 和 QoS 2 消息;
      待发送到客户端的QoS 1 和 QoS 2 消息;
      已被客户端接收,但还没有被确认的QoS 2 消息;
      (可选)待发送到客户端的QoS 0 消息;

  • Will Flag,Will QoS,Will Retain:这三个字段是用来预立“遗嘱”的。预立“遗嘱”的意思是:客户端在连接服务端时,可将预先定义好的主题和对应消息发送给服务端。当它和服务端连接断开时,服务端将及时地发布这段消息到预定的主题。

    • Will Flag:
      位置:连接标识字节的第2位(Bit 2)
      含义:此标志位指示客户端是否指定了一个遗嘱(Will)消息。如果Will Flag 被设置为1,表明客户端希望在连接意外断开时,服务器能够发布一个预定义的遗嘱消息到指定的遗嘱主题。如果设置为0,则没有遗嘱消息被指定。
    • Will QoS (遗嘱服务质量);
      位置:连接标识字节的第3和第4位(Bit 3 和 Bit 4)
      含义:这两个位共同表示遗嘱消息的服务质量(QoS)。QoS 级别可以是0(最多一次交付),1(至少一次交付),或2(恰好一次交付)。只有当Will Flag 被设置为1时,这两个位才有效。
    • Will Retain:
      位置:连接标识字节的第5位(Bit 5)
      含义:此标志位决定遗嘱消息是否被服务器保留。如果Will Retain 被设置为1,服务器将保留遗嘱消息,并将其作为新订阅者的默认消息。如果设置为0,遗嘱消息将不会被服务器保留。
  • Password Flag:表示客户端将提供密码进行认证。如果设置为0,则不包含密码信息。

    • 位置:连接标识字节的第6位(Bit 6)
      含义:此标志位指示是否在CONNECT Packet 的载荷中包含密码信息。如果Password Flag 被设置为1
  • User Name Flag:此标志位指示是否在CONNECT Packet 的载荷中包含用户名信息。

    • 位置:连接标识字节的第7位(Bit 7)
    • 如果User Name Flag 被设置为1,表示客户端将提供用户名进行认证。如果设置为0,则不包含用户名信息。

二、载荷内容详解

CONNECT 包的载荷一定包含 Client Identifier 字段,可能包含 Will Topic, Will Message, User Name, Password 字段(由可变头部中的各标记位决定)。这些字段若存在,一定要按照以上顺序排列。

  • Client Identifier:由客户端自己指定的 ID,服务端据此来标识客户端(以此关联Session)。因此不同客户端之间的 ID 不能重复(重复将视为同一客户端)。它使用 UTF-8编码,长度通常在1 ~ 23个字节之间,通常包含 [0-9a-zA-Z] 中的字符(允许例外,由服务端的实现决定)。若客户端 ID 不存在,服务端需要为其指定一个独一无二的 ID。在这种情况下,客户端必须设置 CleanSession 为 1;若不设为 1,服务端需要 响应 CONNACK 包,其中 返回 code 0x02(Identifier rejected), 随后断开连接。
  • Will Topic,Will Message:当 Will Flag 值为 1 时存在,均采用 UTF-8 编码。
  • User Name:采用 UTF-8 编码,用来做身份认证。
  • Password:长度不固定,头两个字节用来指明密码的字节数,之后是密码的字节,结构如下:
+-----------+---+---+---+---+---+---+---+---+
|    Bit    | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------+---+---+---+---+---+---+---+
|  byte 1   |        Data length MSB        |
+-------------------------------------------+
|  byte 2   |        Data length LSB        |
+-------------------------------------------+
|  byte 3...|      Data, if length > 0.     |
+-------------------------------------------+

在 MQTT 协议中,字符串均采用的 UTF-8 编码

+------------------------------------------------------------+
|   Bit   |  7  |  6  | 5   |  4  |  3  |  2  |  1  |    0   |
+------------------------------------------------------------+
|  byte1  |                 String length MSB                |
+------------------------------------------------------------+
|  byte2  |                 String length LSB                |
+------------------------------------------------------------+
| byte3...|    UTF-8 Encoded Character Data, if length > 0   |
+------------------------------------------------------------+

一些情况的处理方式:
注意:在一个客户端在线的情况下,同一客户端(相同 Client ID)再次连接服务端,服务端需断开之前的连接;客户端在发送 CONNECT 包后,可以再立即发送其他的包,而无需等待 CONNACK 包的响应。但服务端收到 CONNECT 包后,若拒绝连接,一定不能处理客户端在 CONNECT 包后发送的包。


总结

下一个类型:CONNACK Packet

显示全文