MQTT协议知识点讲解
已经几天没发博客了,我又回来啦,头晕乎乎应该是缺少维生素RMB了,话不多说,且看以下:
一、MQTT协议基本格式介绍
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
MQTT是基于TCP的应用层协议,与http、ftp协议是处于同一层。几乎所有使用ESP32接入IOT物联网的项目中,都用的是MQTT协议,因此我们有必要学习MQTT协议基本内容。
1.MQTT基本格式
MQTT协议节本框架内容如下图所示
1)固定包头
固定包头由如下构成
第一字节4-7位用于表示报文类型,0-3位用于每种报文的特殊标志位。
报文类型(4-7位):
报文的特殊标志位(0-3位):
这个表中被标识为预留的,也需要填相应的值,如果接收方收到不可用的标识,接收方必须关闭网络连接,由此可见,这个特殊标志表对PUBLISH发布报文是最有用的。
- DUP——发布消息的副本。用来在保证消息的可靠传输,如果设置为1,则在下面的变长中增加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。
- QoS——发布消息的服务质量,QoS0:接收方最多能接收到一次,QoS1:接收方最少收到一次,QoS2:接收方只能收到一次。
- RETAIN—— PUBLISH 数据包中 Retain 表示为1的消息,Broker收到消息后,将会为该主题保存该Retained消息。当有新的订阅者订阅该主题时,Broker 会将这个消息立即发送给新的订阅者。
固定包头第二字节开始表示剩余长度,该长度是后面的可变报文头加消息负载的总长度,该字段最多允许四个字节。剩余长度字段单个字节最大值为16进制0x7F,也就是说,单个字节可以描述的最大长度是127字节。MQTT协议规定,单个字节第7位(最高位)若为1,则表示后续还有字节存在,第7位(最高位)起“延续位”的作用,所以最后一字节最大值只能是0x7F。
例子如下:
比如剩余长度三个字节如下
0b1110 0111 = 0xE7 去掉第7位值为0x67(第7位是1,说明后面一个字节也表示剩余长度)
0b1000 1101 = 0x8D去掉第7位值为0x0D(第7位是1,说明后面一个字节也表示剩余长度)
0b0001 0001 = 0x11 去掉第7位值为0x0D(第7位是0,表示后面没有长度)
计算方法位:剩余长度len = 0x67 + (0x0D<<7) + (0x11<<14)
2)可变报头与载荷
不一定每个报文都有,内容根据报文类型不同而不同,以下结合不同的报文类型说明一下可变包头与载荷内容
二、CONNECT与CONNECTACK报文
CONNECT报文是用于客户端向服务器发起连接请求的报文,服务器会验证其中的信息并且返回CONNECTACK告知客户端结果,在向Broker发布、订阅消息之前,需要先向服服务器发起CONNECT报文,得到肯定回应后才能进行后续操作。CONNECT包含固定包头、可变包头、消息载荷。CONNECTACK包含固定包头、可变包头。
CONNECT报文可变包头由如下构成:
协议名(Protocol Name)、协议等级(Protocol Level)、连接标志(Connect Flags)、保持连接(Keep Alive)
主要看看连接标志,连接标志用于指示payload域存在哪些内容
Clean Session:标识客户端是0否1建立一个持久化的会话,当Clean Session的标识设为 0 时,代表客户端希望建立一个持久会话的连接,代理服务器将存储该客户端订阅的主题和未接受的消息,否则(设置为1) 代理服务器不会存储这些数据,同时在建立连接时清除这个客户端之前存在的持久化会话所保存的数据。
Will Retain、Will QoS、Will Flag这三个与遗愿相关。当 Broker 检测到 Client 非正常断开连接时,就会向 Client 遗嘱主题中发布相应的遗嘱消息 LWT
- Will Flag:是否使用 LWT 遗嘱消息;
- Will QoS:发布遗嘱消息时的 QoS 等级
- Will Retain:遗嘱消息的 Retain 标识
如果连接标志包含所有内容,必须按这个顺序出现:客户端标识符、遗嘱主题、遗嘱消息、用户名、密码。假设我们不使用Will功能,那么payload内容就是如下:
CONNECT ACK报文可变包头由如下构成:
连接确认标志,返回码
当CONNECT报文中的Clean Session标志设置为1时,当前会话标志为0
三、PUBLISH(发布)与SUBSCRIBE(订阅)报文
这里先说一下订阅与推送过程
终端设备手机、电脑订阅了(Subscribe)主题“temperature”,这时候温度传感器向主题“temperature”发布了(Publish)了一条消息,内容是“21℃”,MQTT-Broker收到这条消息后,会查看有哪些客户端订阅了这条消息主题,找到之后就会把这条消息内容转发给相应的客户端(手机、电脑)
Topic(主题):
topic在MQTT里面是消息传递的基础,代表了消息的流向,从本质上看,topic是一串字符串,可以使用正斜杠对topic进行分级。
例子:
比如我向A代理服务器订阅了如下主题消息
“/编程知识/嵌入式/C语言”,当有其他人向A服务器推送了主题“/编程知识/嵌入式/C语言”的消息时候,那么代理服务器就会把这条消息推送给我,如果别人推送的是“/编程知识/嵌入式/C++”,由于主题不匹配,那么代理服务器就不会把这条消息推送给我们。
#和+通配符
topic支持通配符进行订阅,比如说
订阅“/编程知识/嵌入式/#”的主题,那么订阅者就会收到诸如“/编程知识/嵌入式/C++”、“/编程知识/嵌入式/C”、”/编程知识/嵌入式/C/函数指针用法“等等之类的消息。+与#的区别在于+只能匹配当前一层,#能匹配往下所有。
订阅报文(SUBSCRIBE)
订阅回应报文(SUBACK)
取消订阅报文与ACK与上述两个报文类似,不同在于没有服务质量要求Qos
发布报文(PUBLISH)
发布回应报文(PUBACK)
发布消息回执(PUBREC)、发布释放(PUBREL)、发布完成(PUBCOMP)报文与发布回应除报文类型外均一致。接下来看下三种不同的消息等级他们的消息流程以及发送的报文是怎样的。
QoS=0(接收方最多收到一次)
QoS=1(接收方最少收到一次)
QoS=2(接收方只收到一次)
最后附上相关资料:
ESP32教程资料链接:
https://pan.baidu.com/s/1kCjD8yktZECSGmHomx_veg?pwd=q8er
提取码:q8er
配套源码下载地址:
esp32-board: esp32开发板配套的经典例程
鉴于实验需要开发板的支持,我也设计了一款ESP32开发板,包含部分传感器模块,1.69寸LCD高亮屏,Type-C一键下载,方便大家学习和做各种实验。开发板链接如下:
请大家多多支持。