MQTT 是基于 Publish/Subscribe 模式的物联网通信协议,凭借简单易实现、支持 QoS、报文小等特点,占据了物联网协议的半壁江山. MQTT在物联网方向的开发出现的频率非常高, 因此从事该行业方向开发有必要对其进行下系统的学习
官方文档传送门 mqtt官网 mqtt中文网 mqtt 3.1.1 英文文档 mqtt 5.0 英文文档 b站mqtt教程
注意:
MQTT协议广泛应用于物联网、移动互联网、智能硬件、车联网、电力能源等领域。
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:
网络链接
由底层传输协议提供给MQTT使用的架构
应用消息
指通过MQTT在网络中传输的应用程序数据。 当应用消息通过MQTT传输的时候会附加上质量服务(QoS)和话题名称。
客户端
一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的网络连接。客户端可以
服务端
MQTT服务器被称为"消息代理"(Broker),它可以是一个应用程序或一台设备。是位于消息发布者和订阅者之间,它可以:
主题名
指附着于应用消息的标签,服务端用它来匹配订阅。服务端给每个匹配到的客户端发送一份应用信息的拷贝。
主题过滤器
是包含在订阅里的一个表达式,用来表示一个或多个感兴趣的话题。话题过滤器可以包含通配符。
MQTT控制包
通过网络连接发送的包含一定信息的数据包。MQTT规范定义了14个不同类型的控制包,其中一个(PUBLISH包)用来传输应用信息。
发布/订阅、主题、会话
至此可以初步总结下mqtt工作流程
MQTT协议中定义了一些方法(也被称为动作),来于表示对确定资源所进行操作。 这个资源可以代表预先存在的数据或动态生成数据,这取决于服务器的实现。 通常来说,资源指服务器上的文件或输出。主要方法有:
在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。MQTT数据包结构如下:
存在于所有MQTT数据包中, 头包含两部分内容: 报文头(byte1)和剩余消息报文长度(从byte2开始,长度为1-4字节)
位置:第一个字节(Byte 1) 中的7-4个bit位(Bit[7-4]),表示4位无符号值 通过第一个字节的高4位确定消息报文的类型,4个bit位能确定16种类型,其中0000和1111是保留字段。
MQTT消息报文类型如下:
报文类型 | 字段值 | 数据方向 | 描述 | 7-4bit值 |
---|---|---|---|---|
保留 | 0 | 禁用 | 保留字段 | 0000 |
CONNECT | 1 | Client—>Server | 客户端连接到服务器 | 0001 |
CONNACK | 2 | Server —> Client | 连接确认 | 0010 |
PUBLISH | 3 | Client—>Server | 发布消息 | 0011 |
PUBACK | 4 | Client—>Server | 发布确认(QoS1) | 0100 |
PUBREC | 5 | Client—>Server | 消息已接收(Qos2 第一阶段) | 0101 |
PUBREL(发布的消息已释放) | 6 | Client—>Server | 消息释放(QoS2 第二阶段) | 0110 |
PUBCOMP | 7 | Client—>Server | 发布结束(QoS2 第三阶段) | 0111 |
SUBSCRIBE | 8 | Client—>Server | 客户端订阅请求 | 1000 |
SUBACK | 9 | Server —> Client | 服务端订阅确认 | 1001 |
UNSUBACRIBE | 10 | Client—>Server | 客户端取消订阅 | 1010 |
UNSUBACK | 11 | Server —> Client | 服务端取消订阅确认 | 1011 |
PINGREQ | 12 | Client—>Server | 客户端发送心跳 | 1100 |
PINGRESP | 13 | Server —> Client | 服务端回复心跳 | 1101 |
DISCONNECT | 14 | Client—>Server | 客户端断开连接请求 | 1110 |
AUTH(V5.0使用) | 15 | Client—>Server | 认证数据交换 | 1111 |
位置:第一个字节中的0-3个bit位(Bit[3-0])。意思是字节位Bit[3-0]用作报文的标识。 首字节的低4位(bit3~bit0)用来表示某些报文类型的控制字段,实际上只有少数报文类型有控制位,如下图:
报文类型 | 固定头标记 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|
CONNECT | 保留 | 0 | 0 | 0 | 0 |
CONNACK | 保留 | 0 | 0 | 0 | 0 |
PUBLISH | 保留 | DUP | Qos | QoS | RETAIN |
PUBACK | 保留 | 0 | 0 | 0 | 0 |
PUBREC | 保留 | 0 | 0 | 0 | 0 |
PUBREL(发布的消息已释放) | 保留 | 0 | 0 | 0 | 0 |
PUBCOMP | 保留 | 0 | 0 | 0 | 0 |
SUBSCRIBE | 保留 | 0 | 0 | 0 | 0 |
SUBACK | 保留 | 0 | 0 | 0 | 0 |
UNSUBACRIBE | 保留 | 0 | 0 | 0 | 0 |
UNSUBACK | 保留 | 0 | 0 | 0 | 0 |
PINGREQ | 保留 | 0 | 0 | 0 | 0 |
PINGRESP | 保留 | 0 | 0 | 0 | 0 |
DISCONNECT | 保留 | 0 | 0 | 0 | 0 |
图1
图2
图3
注意:
目前Bit[3-0]只在PUBLISH协议中使用有效,并且表中指明了是MQTT 3.1.1版本(如上表)。 对于其它MQTT协议版本,内容可能不同。所有固定头标记为"保留"的协议类型, Bit[3-0]必须保持与表中保持一致,如SUBSCRIBE协议,其Bit 1必须为1。 如果接收方接收到非法的消息,会强行关闭当前连接。
下图则是MQTT 5.0 版本标志位
Keep Alive是以秒为单位的时间间隔。用2字节表示,它指的是客户端从发送完成一个控制包到开始发送下一个的最大时间间隔。客户端有责任确保两个控制包发送的间隔不能超过Keep Alive的值。如果没有其他控制包可发,客户端必须发送PINGREQ包
心跳的作用:
更多可变头介绍可见mqtt官网 3.1.2.1 -3.1.2.11
有些报文类型是包含Payload的,Payload意思是消息载体的意思. 如PUBLISH的Payload就是指消息内容(应用程序发布的消息内容)。而CONNECT的Payload则包含ClientIdentifier,Will Topic,Will Message,Username,Password等信息。包含payload的报文类型如下
到目前为止,比较流行的 MQTT Broker 有几个:
从支持 MQTT5.0、稳定性、扩展性、集群能力等方面考虑,EMQX 的表现应该是最好的。
而下面, 我们将介绍万物互联消息引擎 —— EMQ系列消息引擎 使用基于 Erlang/OTP 平台开发的开源物联网 MQTT 消息服务器 —— EMQ X (Erlang/Enterprise/Elastic MQTT Broker) 来实现基于mqtt协议特性以及更多拓展特性的消息队列