MQTT协议之CONNECT报文

简介        

        客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文。

        CONNECT报文包括了固定报头、可变报头以及有效载荷部分。

固定报头

        固定报头主要由两部分组成,第一个字节已经固定是0x10;第二个字节开始是剩余长度。

补充一下剩余长度

        从图中不难看出,剩余长度可理解为可变报头和有效载荷的长度之和。需要注意的是,剩余长度采用变长编码方案。对于小于128的,使用一个字节就可以表示;而大于等于128的,需要根据编码方式进行处理。

可变报头

        CONNECT报文的可变报头按下列次序包含四个字段:协议名(Protocol Name),协议级别 (Protocol Level),连接标志(Connect Flags)和保持连接(Keep Alive)。

协议名

        协议名已经固定,共计6个字节,对应的十六进制是00 04 4D 51 54 54。

协议级别

        协议级别固定为单字节0x04。

连接标志

         连接标志决定了有效载荷的部分组成,这里先赋值为0xC2。也就是第7位用户名,第6位密码以及第1位清理会话位置1。

保持连接

        保持连接笔者暂时取100s计算,也就是对应0x00 0x64。

有效载荷

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

        根据笔者在可变报头中的连接标志设定,这里包含客户端标识符(无须设置,其必须存在)、用户名以及密码。

客户端标识符

关于UTF-8编码的补充

        UTF-8格式即在字符串前面加上两个字节来表示字符串长度。

用户名

密码

通过网络调试助手连接阿里云

        首先在阿里云创建产品及设备,设备创建后可以查看MQTT连接参数。

        图中从上到下分别是有效载荷中的客户端ID,用户名以及密码。需要将三者转换成十六进制模式。

        按照固定报头、可变报头、有效载荷的顺序,得到转换成十六进制的报文组合,需要注意部分报头需要UTF-8的格式。

        笔者根据自己设备的MQTT参数,转换得到适用于自己的报文。

        网络调试助手设置如下图,选择TCP Client协议,远程主机地址和端口参考阿里云设备的MQTT参数。发送格式选为hex,也就是十六进制。

        发送CONNECT报文,当服务器返回的数据最后一字节为0x00时,可以视为与阿里云连接成功。

        发送CONNECT报文前,设备离线

        发送CONNECT报文后,设备在线

### MQTT 连接确认响应协议说明 当MQTT客户端尝试连接到服务器时,会发送CONNECT报文给Broker。Broker处理该请求并回应CONNACK报文来指示连接的结果[^1]。 #### CONNACK 报文结构 CONNACK固定头由两个字节组成: | 字段 | 含义 | | --- | --- | | 第一字节 | 总是为`0x20`表示这是CONNACK报文 | | 第二字节 | 包含标志位和返回码 | 第二字节中的低7位用于携带返回码(Return Code),它决定了连接是否成功以及失败的原因。常见的返回码包括但不限于: - `0`: 连接已接受 (Connection Accepted) - `1`: 不允许的协议版本 (Unacceptable Protocol Version) - `2`: 客户端标识符被拒绝 (Identifier rejected) 对于特定错误如`MQTT_CONNECT_BAD_CLIENT_ID`或`MQTT_DISCONNECTED`,这通常意味着客户端ID不符合预期格式或是无法建立稳定链接。 针对Arduino ESP8266/ESP32设备作为MQTT客户端与阿里云IoT平台通信过程中可能出现的问题,比如遇到了`mqtt connect err:2`的情况,可能是因为设备三元组(ProductKey, DeviceName, DeviceSecret)配置不正确或者是网络环境不稳定造成的握手异常[^2][^3]。 为了排查此类问题,建议检查以下几点: - 确认所使用的客户端ID遵循了目标MQTT Broker的要求; - 验证证书文件路径及权限设置无误; - 测试其他类型的认证方式以排除单一因素影响; - 使用调试工具捕获详细的日志信息以便进一步分析原因所在; ```cpp // 示例代码展示如何初始化一个安全的MQTT连接 WiFiClientSecure client; client.setFingerprint("xx xx xx ..."); // 设置TLS指纹验证 PubSubClient mqtt(client); mqtt.connect("clientId", "username", "password"); if (!mqtt.connected()) { Serial.println(mqtt.state()); // 打印当前状态帮助诊断问题 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值