admin 管理员组文章数量: 893893
【MQTT】MQTT协议学习
文章目录
- MQTT协议
- 简述
- 特点
- MQTT消息的QoS(服务质量)
- MQTT支持三种QoS等级:
- 协议实现方式
- MQTT协议数据包(控制报文)结构
- MQTT固定头
- MQTT数据包类型
- 标识位
- 剩余长度(Remaining Length)
- MQTT可变头
- Payload消息体
- 原因码 Reason Code
- 订阅主题--字符串匹配
MQTT协议
简述
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
特点
本协议运行在TCP/IP,或其它提供了有序、可靠、双向连接的网络连接上。它有以下特点:
- 使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。
- 消息传输不需要知道负载内容。
- 提供三种等级的服务质量。
- 很小的传输消耗和协议数据交换,最大限度减少网络流量。
- 异常连接断开发生时,能通知到相关各方。
MQTT消息的QoS(服务质量)
MQTT支持三种QoS等级:
QoS 0 : “最多一次”,尽操作环境所能提供的最大努力分发消息。分发的消息可能丢失或重复。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久后还会有第二次发送。
QoS 1 :“至少一次”,确保消息可以到达,但消息可能会重复。
QoS 2 :“只有一次”,确保消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。
协议实现方式
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
客户端 Client
使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以
- 打开连接到服务端的网络连接
- 发布应用消息给其它相关的客户端
- 订阅以请求接受相关的应用消息
- 取消订阅以移除接受应用消息的请求
- 关闭连接到服务端的网络连接
服务端 Server
一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端
- 接受来自客户端的网络连接
- 接受客户端发布的应用消息
- 处理客户端的订阅和取消订阅请求
- 转发应用消息给符合条件的已订阅客户端
- 关闭来自客户端的网络连接
应用消息
MQTT传输的消息分为:主题(Topic)和负载(payload)
两部分:
- Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);
- payload,可以理解为消息的内容,是指订阅者具体要使用的内容。
MQTT协议数据包(控制报文)结构
在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。MQTT数据包结构如下:
- (1)固定头(Fixed header)。存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。
- (2)可变头(Variable header)。存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。
- (3)消息体(Payload)。存在于部分MQTT数据包中,表示客户端收到的具体内容。
MQTT固定头
固定头存在于所有MQTT数据包中,其结构如下:
比特位 | 7 6 5 4 | 3 2 1 0 |
---|---|---|
byte 1 | MQTT控制报文的类型 | 用于指定控制报文类型的标志位 |
byte 2 | 剩余长度 |
MQTT数据包类型
位置:Byte 1中bits 7-4。
相于一个4位的无符号值,类型、取值及描述如下:
MQTT的消息类型
类型 值 报文流动方向 描述
CONNECT 1 C ->S 客户端请求与服务端建立连接
CONNACK 2 S ->C 服务端确认连接建立
PUBLISH 3 C<->S 发布消息
PUBACK 4 C<->S 收到发布消息确认
PUBREC 5 C<->S 发布消息收到
PUBREL 6 C<->S 发布消息释放
PUBCOMP 7 C<->S 发布消息完成
SUBSCRIBE 8 C ->S 订阅请求
SUBACK 9 S ->C 订阅确认
UNSUBSCRIBE 10 C ->S 取消订阅
UNSUBACK 11 S ->C 取消订阅确认
PINGEQ 12 C ->S 客户端发送PING(连接保活)命令
PINGRSP 13 S ->C PING命令回复
DISCONNECT 14 C ->S 断开连接
详解:
-
CONNECT
– 连接服务端:客户端到服务端的网络连接建立后, 客户端发送给服务端的第一个报文必须是CONNECT报文。
-
CONNACK
– 确认连接请求:服务端发送CONNACK报文响应从客户端收到的CONNECT报文。 服务端发送给客户端的第一个报文必须是CONNACK。如果客户端在合理的时间内没有收到服务端的CONNACK报文, 客户端应该关闭网络连接。合理的时间取决于应用的类型和通信基础设施。
-
PUBLISH
– 发布消息:PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。
-
PUBACK
– 发布确认:PUBACK报文是对QoS 1等级的PUBLISH报文的响应。
-
PUBREC
– 发布收到( QoS 2, 第一步):PUBREC报文是对QoS 2的PUBLISH报文的响应。 它是QoS 2等级协议交换的第二个报文。
-
PUBREL
– 发布释放( QoS 2, 第二步):PUBREL报文是对PUBREC报文的响应。 它是QoS 2等级协议交换的第三个报文。
-
PUBCOMP
– 发布完成( QoS 2, 第三步):PUBCOMP报文是对PUBREL报文的响应。 它是QoS 2等级协议交换的第四个也是最后一个报文。
-
SUBSCRIBE
— 订阅主题:客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。 每个订阅注册客户端关心的一个或多个主题。 为了将应用消息转发给与那些订阅匹配的主题, 服务端发送PUBLISH报文给客户端。 SUBSCRIBE报文也( 为每个订阅) 指定了最大的QoS等级, 服务端根据这个发送应用消息给客户端。
-
SUBACK
– 订阅确认:服务端发送SUBACK报文给客户端, 用于确认它已收到并且正在处理SUBSCRIBE报文。
-
UNSUBSCRIBE
– 取消订阅:客户端发送UNSUBSCRIBE报文给服务端, 用于取消订阅主题。
-
UNSUBACK
– 取消订阅确认:服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。
-
PINGREQ
– 心跳请求:客户端发送PINGREQ报文给服务端的。 用于:
-
在没有任何其它控制报文从客户端发给服务的时, 告知服务端客户端还活着。
-
请求服务端发送 响应确认它还活着。
-
使用网络以确认网络连接没有断开。
-
-
PINGRESP
– 心跳响应:服务端发送PINGRESP报文响应客户端的PINGREQ报文。 表示服务端还活着。
-
DISCONNECT
– 断开连接:DISCONNECT报文是客户端发给服务端的最后一个控制报文。 表示客户端正常断开连接。
标识位
位置:Byte 1中bits 3-0。
在不使用标识位的消息类型中,标识位被作为保留位。如果收到无效的标志时,接收端必须关闭网络连接:
(1)DUP:发布消息的副本。用来在保证消息的可靠传输,如果设置为1,则在下面的变长中增加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。
(2)QoS:发布消息的服务质量,即:保证消息传递的次数
Ø00:最多一次,即:<=1
Ø01:至少一次,即:>=1
Ø10:一次,即:=1
Ø11:预留
(3)RETAIN: 发布保留标识,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果没有那么推送至当前订阅者后释放。
剩余长度(Remaining Length)
地址:Byte 2。
剩余长度是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。MQTT控制报文总长度等于固定报头的长度加上剩余长度。
MQTT可变头
MQTT控制报文中包含一个可变头,它位于固定头和消息体之间。可变头的内容因报文类型而不同,较常的应用是作为包的标识。
可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。
部分类型MQTT控制报文的可变报头部分包含了2个字节的报文标识符字段,这些类型的包有:PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK。
需要报文标识符的MQTT控制报文如下表所示。
名字 | 值 |
---|---|
CONNECT | 不需要 |
CONNACK | 不需要 |
PUBLISH | 需要(如果QoS>0) |
PUBACK | 需要 |
PUBREC | 需要 |
PUBREL | 需要 |
PUBCOMP | 需要 |
SUBSCRIBE | 需要 |
SUBACK | 需要 |
UNSUBSCRIBE | 需要 |
UNSUBACK | 需要 |
PINGREQ | 不需要 |
PINGRESP | 不需要 |
DISCONNECT | 不需要 |
AUTH | 不需要 |
Payload消息体
Payload消息体位MQTT数据包的第三部分,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:
- (1)CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。
- (2)SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS。
- (3)SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
- (4)UNSUBSCRIBE,消息体内容是要订阅的主题。
原因码 Reason Code
原因码是一个单字节无符号数,用来指示一次操作的结果。小于0x80的原因码指示某次操作成功完成,通常用0来表示。大于等于0x80的原因码用来指示操作失败。
CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,DISCONNECT和AUTH控制报文的可变报头有一个单字节的原因码。SUBACK和UNSUBACK报文的载荷字段包含一个或多个原因码。
原因码如下表所示:
原因码 | 名称 | 报文 | |
---|---|---|---|
Dec(十进制) | Hex(16进制) | ||
0 | 0x00 | 成功 | CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH |
0 | 0x00 | 正常断开 | DISCONNECT |
0 | 0x00 | 授权的QoS 0 | SUBACK |
1 | 0x01 | 授权的QoS 1 | SUBACK |
2 | 0x02 | 授权的QoS 2 | SUBACK |
4 | 0x04 | 包含遗嘱的断开 | DISCONNECT |
16 | 0x10 | 无匹配订阅 | PUBACK, PUBREC |
17 | 0x11 | 订阅不存在 | UNSUBACK |
24 | 0x18 | 继续认证 | AUTH |
25 | 0x19 | 重新认证 | AUTH |
128 | 0x80 | 未指明的错误 | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT |
129 | 0x81 | 无效报文 | CONNACK, DISCONNECT |
130 | 0x82 | 协议错误 | CONNACK, DISCONNECT |
131 | 0x83 | 实现错误 | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT |
132 | 0x84 | 协议版本不支持 | CONNACK |
133 | 0x85 | 客户标识符无效 | CONNACK |
134 | 0x86 | 用户名密码错误 | CONNACK |
135 | 0x87 | 未授权 | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT |
136 | 0x88 | 服务端不可用 | CONNACK |
137 | 0x89 | 服务端正忙 | CONNACK, DISCONNECT |
138 | 0x8A | 禁止 | CONNACK |
139 | 0x8B | 服务端关闭中 | DISCONNECT |
140 | 0x8C | 无效的认证方法 | CONNACK, DISCONNECT |
141 | 0x8D | 保活超时 | DISCONNECT |
142 | 0x8E | 会话被接管 | DISCONNECT |
143 | 0x8F | 主题过滤器无效 | SUBACK, UNSUBACK, DISCONNECT |
144 | 0x90 | 主题名无效 | CONNACK, PUBACK, PUBREC, DISCONNECT |
145 | 0x91 | 报文标识符已被占用 | PUBACK, PUBREC, SUBACK, UNSUBACK |
146 | 0x92 | 报文标识符无效 | PUBREL, PUBCOMP |
147 | 0x93 | 接收超出最大数量 | DISCONNECT |
148 | 0x94 | 主题别名无效 | DISCONNECT |
149 | 0x95 | 报文过长 | CONNACK, DISCONNECT |
150 | 0x96 | 消息太过频繁 | DISCONNECT |
151 | 0x97 | 超出配额 | CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT |
152 | 0x98 | 管理行为 | DISCONNECT |
153 | 0x99 | 载荷格式无效 | CONNACK, PUBACK, PUBREC, DISCONNECT |
154 | 0x9A | 不支持保留 | CONNACK, DISCONNECT |
155 | 0x9B | 不支持的QoS等级 | CONNACK, DISCONNECT |
156 | 0x9C | (临时)使用其他服务端 | CONNACK, DISCONNECT |
157 | 0x9D | 服务端已(永久)移动 | CONNACK, DISCONNECT |
158 | 0x9E | 不支持共享订阅 | SUBACK, DISCONNECT |
159 | 0x9F | 超出连接速率限制 | CONNACK, DISCONNECT |
160 | 0xA0 | 最大连接时间 | DISCONNECT |
161 | 0xA1 | 不支持订阅标识符 | SUBACK, DISCONNECT |
162 | 0xA2 | 不支持通配符订阅 | SUBACK, DISCONNECT |
订阅主题–字符串匹配
在 MQTT 中,订阅仅仅是简单的字符串匹配。为提高处理效率,只允许如下两种通配符:
#
以递归方式匹配,直到字符串结束+
匹配下一个/
之前的内容
#发布主题:
> test/001/aaa
> test/001/bbb
> test/002/aaa
> test/002/bbb
> test/003/aaa
> test/003/bbb#订阅主题:
> test/# --匹配test下所有内容
> test/+/aaa --匹配([test/001/aaa],[test/002/aaa],[test/003/aaa])
参考内容:
-
MQTT 中文网
-
MQTT 英文官网
资料:
- MQTT3.1.1中文文档html+PDF
本文标签: MQTTMQTT协议学习
版权声明:本文标题:【MQTT】MQTT协议学习 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1688192165h190243.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论