MQTT协议详解及开发教程(四)MQTT协议报文格式
推荐一款稳定的基于C编写的MQTT Client开源库 cMQTT
MQTT协议详解及开发教程(一)MQTT协议概述
MQTT协议详解及开发教程(二)MQTT服务器EMQx搭建
MQTT协议详解及开发教程(三)MQTT Client工具软件选择及简单测试
前言
在前面的文章中,我们对MQTT的应用场景,MQTT服务器搭建、MQTT client工具测试进行了简单的描述,对MQTT有了初步的了解,从本文开始,将会详细的分析MQTT协议内容。
1.MQTT 控制报文结构
名称 | 备注 |
---|---|
Fixed header固定头 | 所有的控制报文都包含 |
Variable header可变报头 | 部分控制报文包含 |
Payload有效载荷 | 部分控制报文包含 |
2 固定头
每个MQTT控制报文都包含了一个固定头,下图描述了固定头的格式
2.1 MQTT控制报文类型
位置:第1个字节,第4~7bit,共4位无符号值,这些值的定义如下表:
名字 | 值 | 报文流动方向 | 描述 |
---|---|---|---|
Reserved | 0 | 禁止 | 保留 |
CONNECT | 1 | 客户端到服务端 | 客户端请求连接服务端 |
CONNACK | 2 | 服务端到客户端 | 连接报文确认 |
PUBLISH | 3 | 双向 | 发布消息 |
PUBACK | 4 | 双向 | QoS 1消息发布收到确认 |
PUBREC | 5 | 双向 | 发布收到(保证交付第一步) |
PUBREL | 6 | 双向 | 发布释放(保证交付第二步) |
PUBCOMP | 7 | 双向 | QoS 2消息发布完成 |
SUBSCRIBE | 8 | 客户端到服务端 | 客户端订阅请求 |
SUBACK | 9 | 服务端到客户端 | 订阅请求报文确认 |
UNSUBSCRIBE | 10 | 客户端到服务端 | 客户端取消订阅请求 |
UNSUBACK | 11 | 服务端到客户端 | 取消订阅报文确认 |
PINGREQ | 12 | 客户端到服务端 | 心跳请求 |
PINGRESP | 13 | 服务端到客户端 | 心跳响应 |
DISCONNECT | 14 | 客户端到服务端 | 客户端断开连接 |
Reserved | 15 | 禁止 | 保留 |
2.2 控制报文标志
固定报头的第1个字节的剩余4位[3-0]包含了每个MQTT控制报文类型特定的标志,如果收到非法的标志,接收者必须关闭网络连接,标志如下,其中任何标记为“Reserved”的标志位,都是保留给以后使用的。
其中:
DUP = 控制报文的重复分发标志
QoS = PUBLISH报文的服务质量等级
RETAIN = PUBLISH报文的保留标志
2.3 剩余长度
位置:从第2个字节开始
剩余长度表示当前报文剩余部分的字节数,包括可变报头和负载数据。剩余长度不包括用于编码剩余长度字段本身的字节数。
剩余长度字段使用了一个变长度编码方案,对于小于128的值,它使用单字节编码,更大的值则按下面的方式处理:
低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码128个(0-127/0x00-0x7F)数值和一个延续位(continuation bit),剩余长度的字段最大4个字节。
举例1:十进制数64,由于小于127,所以会被编码为1个字节,对应的十六进制为 0x40
举例2:十进制321(=65+2128),所以会被编码为2个字节,最低有效位在前,
第1个字节为 65+128 =193,注意这里的128是表示其最高位为1,表示后面还有字节。
第2个字节为2,表示 2128 = 256,
所以本例中的剩余长度编码为 0xC1,0x02,我们去计算的时候是这样:
len = 0xC1&0X7F + 0x02*0x7F // 321
下表中描述了不同字节数表示的剩余长度大小
字节数 | 最小值 | 最大值 |
---|---|---|
1 | 0(0x00) | 127(0x7F) |
2 | 128(0x80, 0x01) | 16383(0xFF,0x7F) |
3 | 16384(0x80, 0x80, 0x01) | 2097151(0xFF, 0xFF, 0x7F) |
4 | 2097152(0x80, 0x80, 0x80, 0x01) | 268435455(0xFF, 0xFF, 0xFF, 0x7F) |
所以MQTT协议 理论上允许发送最大 256MB(268435455)大小的控制报文。
3. 可变报头
某些MQTT控制报文包含了一个可变报头部分,它在固定报头和负载之间,可变报头的内容根据报文类型的不同而不同,可变报头的报文标识符(Packet Identifier)字段存在与多个类型的报文里。
可变报头其实就是MQTT开发中使用的 Packet ID,通过Packet ID 进行一些操作确认。
3.1 报文标识符
报文标识符类型
很多控制报文的可变报头部分包含了两字节的报文标识符字段,这些报文是PUBLISH(QoS>0时),PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCIBE, UNSUBACK.
SUBSCRIBE, UNSUBSCRIBE和PUBLISH(QoS > 0)控制报文必须包含一个非零的16位报文标识符(Packet ID)。客户端每次发送一个新的这些类型报文时,都必须分配一个当前未使用的报文标识符(我们在开发的时候可以做简单的 自增packet_id++)。如果一个客户端要重发这个特殊的控制报文,爱随后重发的那个报文时,它必须使用相同的标识符。当客户端处理完这个报文对应的确认后,这个报文标识符就可以释放了,也就是可以重新使用。
Qos1的PUBLISH 对应的是PUBACK, Qos2的PUBLISH 对应的是PUBCOMP, 与SUBCRIBE或UNSUBSCRIBE对应的分别是SUBACK或UNSUBACK,服务器返回的Packet ID与客户端发送的是一致的,通过这一机制来实现确认。
Qos设置为0的PUBLISH报文不能包含报文标识符。
PUBACK, PUBREC, PUBREL报文必须包含于最初发送的PUBLISH报文相同的报文描述符,同样的,SUBACK和UNSUBACK必须包含在对应的SUBSCRIBE和UNSUBSCRIBE报文中使用的标识符。
需要包含报文标识符的控制报文
控制报文 | 报文标识符字段 |
---|---|
CONNECT | 不需要 |
CONNACK | 不需要 |
PUBLISH | 需要(如果Qos > 0) |
PUBACK | 需要 |
PUBREC | 需要 |
PUBREL | 需要 |
PUBCOMP | 需要 |
SUBSCRIBE | 需要 |
SUBACK | 需要 |
UNSUBSCRIBE | 需要 |
UNSUBACK | 需要 |
PINGREQ | 不需要 |
PINGRESP | 不需要 |
DISCONNECT | 不需要 |
客户端和服务端彼此独立低分配报文标识符,因此客户端、服务端组合使用相同的报文标识符,可以实现并发的消息交换。
4.有效载荷
某些MQTT控制报文在报文的最后部分包含了一个有效载荷,比如对于PUBLISH来说,有效载荷就是应用消息。下表中列出了需要有效载荷的控制报文类型
控制报文 | 有效载荷 |
---|---|
CONNECT | 需要 |
CONNACK | 不需要 |
PUBLISH | 可选 |
PUBACK | 不需要 |
PUBREC | 不需要 |
PUBREL | 不需要 |
PUBCOMP | 不需要 |
SUBSCRIBE | 需要 |
SUBACK | 需要 |
UNSUBSCRIBE | 需要 |
UNSUBACK | 不需要 |
PINGREQ | 不需要 |
PINGRESP | 不需要 |
DISCONNECT | 不需要 |
5 小结
MQTT协议报文的结构由3部分组成,可以简单的理解为:
(1)固定报头:表示这个报文的类型(CONNECT\PUBLISH…)
(2)可变报头:Packet ID,也就是 报文的 顺序ID。
(3)有效载荷:应用消息。
MQTT协议详解及开发教程(四)MQTT协议报文格式相关推荐
- MQTT协议详解及开发教程(一)MQTT协议概述
推荐一款稳定的基于C编写的MQTT Client开源库<cMQTT> 一 概述 MQTT协议目前在物联网技术中应用非常广泛,各种公有云的IOT平台通信基本上都是按照该协议来实现的,这里先简 ...
- AXI接口协议详解-AXI总线、接口、协议
转自:https://cloud.tencent.com/developer/article/1695010 AXI接口协议详解-AXI总线.接口.协议 AXI 总线 上面介绍了AMBA总线中的两种, ...
- SOME/IP协议详解「3.1.1·服务发现报文的格式」
SOME/IP协议详解「3.1.1·服务发现报文的格式」 点击返回雪云飞星的SOME/IP协议详解「总目录」 SOME/IP协议详解「3.1.1·服务发现报文的格式」 1 SD的SOME/IP格式头 ...
- SOME/IP协议详解「2.1.1·SOME/IP的格式头」
SOME/IP协议详解「2.1.1·SOME/IP的格式头」 点击返回雪云飞星的SOME/IP协议详解「总目录」 SOME/IP协议详解「2.1.1·SOME/IP的格式头」 1 SOME/IP报文 ...
- java解析bt协议详解_【转】bt协议的详细分析
一 BT系统的组成结构 1 普通的Web服务器: 例如Apache或IIS服务器 2 一个静态的种子文件: 即.Torrent文件,采用Bencoding编码 3 Tracke ...
- WebSocket协议详解及应用
标签:websocket WebSocket协议详解及应用(七)-WebSocket协议关闭帧 本篇介绍WebSocket协议的关闭帧,包括客户端及服务器如何发送并处理关闭帧.关闭帧错误码及错误处理方 ...
- HTTP协议详解-前端必备
转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey HTTP协议详解-前端必备 引言 一.HT ...
- IGMP/MLD协议详解
此文已经重新编辑:组播及igmp/mld协议详解(二) 1 IGMP 协议 IGMP用来动态的将各个主机注册到特定局域网中的一个组播组中.主机向本地的组播路由器发送IGMP消息来表明自己所属的组播组. ...
- HTTPS简介以及SSL协议详解
HTTPS简介以及SSL协议详解 1.HTTPS简介 2.SSL协议介绍 2.1.SSL协议的功能 2.2.SSL协议在协议栈的位置 2.3.SSL协议组成 2.3.1.纪录协议的功能 2.3.2.S ...
最新文章
- RONG·基础与未来——规模化园区在数据时代如何实现内生增长?
- 开辟与退出一个新的栈帧常用的汇编语言指令
- 【Linux】一步一步学Linux——objdump命令(254)
- 易语言html规则分析,易语言算法原理浅析【一】(示例代码)
- 每天一个JavaScript实例-canvas绘图
- 从 0 开始手写一个 Spring MVC 框架,向高手进阶
- [算法][算法复杂度]常用算法复杂度速查表
- 数学对于编程来说重要吗?编程大佬眼里的线性代数
- android studio怎么设置log保存txt_【Stata写论文】log命令的使用和分析结果导出
- 自己编写的仿京东移动端的省市联动选择JQuery插件
- nginx对listen端口的优化 -- 第一篇
- cocos2d-x开启Wifi
- c# implicit explicit关键字(隐式和显式数据类型转换)
- python实用例子_Python实用案例 - 随笔分类 - 一入测试深似海 - 博客园
- java调用考勤机_怎样把考勤机上的数据用java程序得到?
- 魔兽世界诞生记(上)
- 自然语言处理技术之词嵌入方法-2
- 计算机有多种技术指标其主频是,计算机有多种技术指标,其中主频是指( )。
- 织梦模板安装后出现中文乱码?
- 生鲜配送如何让“订单管理”变得简单?
热门文章
- HDU 5115 (杀狼,区间DP)
- python保存文件的几种方法
- 【转载】爱奇艺个性化推荐排序实践
- Android开发:ADB真机调试方法
- uniapp - 实现安卓APP实时在线更新APP
- ML之RF:基于葡萄牙银行机构营销活动数据集(年龄/职业/婚姻/违约等)利用Pipeline框架(两种类型特征并行处理)+RF模型预测(调参+交叉验证评估+模型推理)客户是否购买该银行的产品二分类案例
- 【综合】一大波值得攻城狮收藏的软件工具
- 关于Isaac Dealey关于OnTap框架的10个问题
- 论文检测重复率怎么修改
- 具有“高薪缘”的行业和职位发布