推荐一款稳定的基于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,表示 2
128 = 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协议报文格式相关推荐

  1. MQTT协议详解及开发教程(一)MQTT协议概述

    推荐一款稳定的基于C编写的MQTT Client开源库<cMQTT> 一 概述 MQTT协议目前在物联网技术中应用非常广泛,各种公有云的IOT平台通信基本上都是按照该协议来实现的,这里先简 ...

  2. AXI接口协议详解-AXI总线、接口、协议

    转自:https://cloud.tencent.com/developer/article/1695010 AXI接口协议详解-AXI总线.接口.协议 AXI 总线 上面介绍了AMBA总线中的两种, ...

  3. SOME/IP协议详解「3.1.1·服务发现报文的格式」

    SOME/IP协议详解「3.1.1·服务发现报文的格式」 点击返回雪云飞星的SOME/IP协议详解「总目录」 SOME/IP协议详解「3.1.1·服务发现报文的格式」 1 SD的SOME/IP格式头 ...

  4. 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报文 ...

  5. java解析bt协议详解_【转】bt协议的详细分析

    一 BT系统的组成结构 1 普通的Web服务器:        例如Apache或IIS服务器 2 一个静态的种子文件:     即.Torrent文件,采用Bencoding编码 3  Tracke ...

  6. WebSocket协议详解及应用

    标签:websocket WebSocket协议详解及应用(七)-WebSocket协议关闭帧 本篇介绍WebSocket协议的关闭帧,包括客户端及服务器如何发送并处理关闭帧.关闭帧错误码及错误处理方 ...

  7. HTTP协议详解-前端必备

    转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey HTTP协议详解-前端必备 引言 一.HT ...

  8. IGMP/MLD协议详解

    此文已经重新编辑:组播及igmp/mld协议详解(二) 1 IGMP 协议 IGMP用来动态的将各个主机注册到特定局域网中的一个组播组中.主机向本地的组播路由器发送IGMP消息来表明自己所属的组播组. ...

  9. HTTPS简介以及SSL协议详解

    HTTPS简介以及SSL协议详解 1.HTTPS简介 2.SSL协议介绍 2.1.SSL协议的功能 2.2.SSL协议在协议栈的位置 2.3.SSL协议组成 2.3.1.纪录协议的功能 2.3.2.S ...

最新文章

  1. RONG·基础与未来——规模化园区在数据时代如何实现内生增长?
  2. 开辟与退出一个新的栈帧常用的汇编语言指令
  3. 【Linux】一步一步学Linux——objdump命令(254)
  4. 易语言html规则分析,易语言算法原理浅析【一】(示例代码)
  5. 每天一个JavaScript实例-canvas绘图
  6. 从 0 开始手写一个 Spring MVC 框架,向高手进阶
  7. [算法][算法复杂度]常用算法复杂度速查表
  8. 数学对于编程来说重要吗?编程大佬眼里的线性代数
  9. android studio怎么设置log保存txt_【Stata写论文】log命令的使用和分析结果导出
  10. 自己编写的仿京东移动端的省市联动选择JQuery插件
  11. nginx对listen端口的优化 -- 第一篇
  12. cocos2d-x开启Wifi
  13. c# implicit explicit关键字(隐式和显式数据类型转换)
  14. python实用例子_Python实用案例 - 随笔分类 - 一入测试深似海 - 博客园
  15. java调用考勤机_怎样把考勤机上的数据用java程序得到?
  16. 魔兽世界诞生记(上)
  17. 自然语言处理技术之词嵌入方法-2
  18. 计算机有多种技术指标其主频是,计算机有多种技术指标,其中主频是指( )。
  19. 织梦模板安装后出现中文乱码?
  20. 生鲜配送如何让“订单管理”变得简单?

热门文章

  1. HDU 5115 (杀狼,区间DP)
  2. python保存文件的几种方法
  3. 【转载】爱奇艺个性化推荐排序实践
  4. Android开发:ADB真机调试方法
  5. uniapp - 实现安卓APP实时在线更新APP
  6. ML之RF:基于葡萄牙银行机构营销活动数据集(年龄/职业/婚姻/违约等)利用Pipeline框架(两种类型特征并行处理)+RF模型预测(调参+交叉验证评估+模型推理)客户是否购买该银行的产品二分类案例
  7. 【综合】一大波值得攻城狮收藏的软件工具
  8. 关于Isaac Dealey关于OnTap框架的10个问题
  9. 论文检测重复率怎么修改
  10. 具有“高薪缘”的行业和职位发布