- 客户端与服务器建立双向连接之后由客户端首先使用此报文与服务器建立MQTT连接,该报文定义了创建MQTT连接的二进制内容。
- 一个网络连接种,客户端只能发送一次此报文给服务端。
- CONNECT报文(数据包)包含3个部分
- 固定包头
- 可变包头
- Payload
1. 固定包头 Fixed Header
固定包头由2-5个字节定义,第一个字节 0x10 ,第2-5个字节描述剩余长度
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (1) |
Reserved |
||||||
|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
byte 2… |
Remaining Length |
2. 可变包头 Variable Header
可变包头包含4个部分
- 协议名称 Protocol Name
- 协议级别 Protocol Level
- 连接标志 Connect Flags
- 保持连接 Keep Alive
2.1 协议名称 Protocol Name
协议名由6个字节表示,使用UTF-8 编码 "MQTT" 字符
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Name |
|||||||||
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 |
2.2 协议级别 Protocol Level
可变包头的第7个字节用来表示协议级别,在5.0版本种用来表示协议版本。 服务器必须验证协议版本。
3.1.1 的值是 0x04
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Level |
|||||||||
byte 7 |
Level(4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Level |
|||||||||
byte 7 |
Version(5) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
2.3 连接标志 Connect Flags
可变包头的第8个字节用来表示连接标志。
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
UserName Flag | Password Flag | Will Retain | Will QoS | Will QoS | Will Flag | Clean Start | 保留位 | |
byte8 | x | x | x | x | x | x | x | 0 |
- Clean Session (Clean Start v5.0)
表示是否启动新会话或延续旧有会话。
CleanStart=1 则客户端和服务器必须丢弃现有会话,并重建新的会话,如果CleanStart=1 ,则CONNEACK 消息种的会话标志始终为0
CleanStart=0 如果服务端(本地存储)存在有与客户端标识符关联的会话,则根据现有会话恢复与客户端的通信,如果服务端不存在旧有会话,服务端则新建一个会话。
客户端的会话状态包括:
- QoS 1和 QoS 2 消息已经发送,但未完全确认。
- 已从服务器收到但尚未完全确认的QoS2 消息
服务端的会话状态包括:
- 存在一个session,即使其余部分为空
- 客户端订阅
- QoS1 QoS2 消息已发送给客户端,但未确认
- QoS1 和 QoS2 消息等待传输到客户端
- 已从客户端收到但未完全确认的 QoS2 消息
- QoS0 消息等待传输到客户端(可选)
会话保留状态根据实际应用场景而定,如果需要CleanSession=0 建立保留会话连接,客户端和服务器都需要一定的本地存储能力。
一般来说,客户端不应该交替使用1或者0。
- Will Flag 遗嘱标志
Will Flag=1 时,表示服务端收到该连接请求后,需要存储消息并和当前网络连接关联,如果非正常断开,服务端必须发布这个遗嘱消息。
遗嘱消息发布的场景包括:
- 服务端监测到一个 I/O 错误或者网络故障
- 客户端在保持连接(keepAlive)时间内未能通讯
- 客户端没有先发送DISCONNECT 报文直接关闭了网络连接
- 由于协议错误服务端关闭了网络连接
如果 Will Flag=1 连接标志中的 QoS和Will Retain 会被服务端用到,同时有效载荷Payload 必须包含 Will Topic 和Will Message 字段。
Will Flag =0 ,表示服务端不发送遗嘱消息,此时连接标志中的 Will QoS 和 Will Retain 必须设置为 0, 并且Payload中不包含Will Topic 和Will Message 字段。
-
Will QoS 遗嘱QoS
连接标志的第3,4位表示Will QoS, 表示发布遗嘱消息时服务质量等级。
如前所述,当Will Flag =1 时,Will QoS 才能有值,可能的值是0,1,2。 -
** Will Retain **
Will Retain 该值取决于 Will Flag,如果WillFlag =0 则 Will Retain 必须为0.
只有当 Will Flag=1 时,Will Retain 的值有可能为 0,1。
Will Retain=1 ,则服务端必须将遗嘱消息当作保留消息发布
Will Retain=0 ,则服务端必须将遗嘱消息当作非保留消息发布 -
UserName Flag
该值决定了决定了 Payload中是否需要包含UserName字段。
UserName Flag=0 则Payload 中不能包含UserName字段
UserName Flag=1 则Payload 中必须包含UserName字段 -
Password Flag
该值决定了决定了 Payload中是否需要包含Password字段。
UserName Flag=0 则Payload 中不能包含Password字段
UserName Flag=1 则Payload 中必须包含Password字段
如果UserName Flag=0 则 Password Flag 也必须为 0.
2.4 保持连接 Keep Alive
可变包头的第9个字节和第10个字节表示保持连接。
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 9 |
Keep Alive MSB |
|||||||
byte 10 |
Keep Alive LSB |
这两个字节表示了客户端和服务端保持交互的最大时间间隔(最大值为65535即18小时12分钟15秒 ),以秒为单位。客户端有责任在该时间间隔之内与服务端保持连接(发送数据包)。
客户端可以随时发送 PINGREQ,并根据PINGRESP消息检查服务端是否正常。
如果KeepAlive 非0, 并且服务端在 KeepAlive 值的1.5倍时间内没有收到来自客户端的数据包,服务端必须断开与客户端的网络连接。
如果KeepAlive =0 ,表示服务端随时可以断开和客户端的网络连接。
来自协议文档的可变包头示例:
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Name |
|||||||||
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 |
Protocol Level |
|||||||||
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 7 |
Level (4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
Connect Flags |
|||||||||
byte 8 |
User Name Flag (1) Password Flag (1) Will Retain (0) Will QoS (01) Will Flag (1) Clean Session (1) Reserved (0) |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
Keep Alive |
|||||||||
byte 9 |
Keep Alive MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 10 |
Keep Alive LSB (10) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
3. Payload
CONNECT 消息中的Payload 内容由 可变包头中的内容决定。依次按以下顺序使用UTF-8编码。
- Client Identifier
- Will Topic
- Will Topic
- Will Message
- User Name
- Password
-
Client Identifier 客户端标识符
客户端的唯一标识,用于识别客户端会话,该字段必须存在。
服务端允许的客户端标识符长度为1-23 个字节。
客户端标识符仅包含如下UTF-8编码的字符:
“0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”
如果ClientIdentifier 超过23个字符,服务器可以允许(扩展)
服务端可以允许客户端提供0字节ClientId,如果这样的话,服务端需要自定义为特殊情况,并为其分配唯一clientId。并且必须将CleanSession设置为1。
如果客户端提供一个零字节ClientId并且CleanSession为0,那么服务端需要拒绝响应,并返回响应码0x02。然后关闭网络连接。 -
Will Topic
如果可变包头的Will Flag=1 ,则Payload中必须包含此字段 -
Will Message
如果Will Flag=1,则Payload中必须包含此字段,该字段包含2个字节的长度和数据部分。数据长度不包含长度本身占用的2个字节。 -
User Name
如果可变包头UserName=1 则Payload 必须包含此字段,用于服务端认证 -
Password
如果可变包头Password=1 则Payload 必须包含此字段。
该字段包含长度和数据两个部分,长度有2个字节,后面跟随长度所定义的字节数。
4. 其他Response说明
服务器可以在同一个Tcp端口支持多个MQTT协议,如果协议版本是MQTT3.1.1,则会按如下方式验证连接
- 如果服务器在建立网络连接后合理时间内没有收到CONNECT数据包,则关闭该连接
- 服务端必须验证CONNECT 数据包是否符合以上定义,如果不符合则应关闭网络连接而不发送CONNACK。
- 服务端可以检查CONNECT数据包内容是否满足任何进一步限制,并可以执行身份验证和授权检查,如果检查失败,可以发送一个带非零码的CONNACK响应。
- 如果验证成功,则服务器将执行以下步骤:
- 如果clientId标识客户端已经连接,服务端必须断开现有连接,保留原有的。
- 服务端必须执行CleanSession 处理
- 服务端必须使用包含返回码的 CONNACK数据包确认CONNECT数据包
- 开始消息传递