简介
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,是物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和控制器的通信协议。
MQTT运行于TCP之上,属于应用层协议。
在面板项目中也广泛用到了MQTT协议,接下来将会从三个方面来介绍如何使用MQTT
- MQTT 的基础知识介绍
- 使用docker 和docker-compose来搭建MQTT Broker
- 使用iOS原生App和MQTT Broker进行通信,并透过MQTT Client 模拟发布订阅
MQTT 基础
MQTT消息格式
每条MQTT命令消息的消息头都包含一个固定的报头,有些消息会携带一个可变报文头和一个负荷。消息格式如下:
固定报文头|可变报文头|负荷
-
固定报文头(Fixed Header)
最少有两个字节,第一个字节包含消息的类型(Message Type)和QoS级别等标志位。第二个字节开始是剩余长度字节,该长度是后面的可变报文头加消息负载的总长度,该字段最多允许四个字节。
剩余长度字段单个字节的最大值为0x7F. 也就是127个字节。MQTT协议规定,单个字节的最高位如果是1,表示后续还有字节存在,第八位起延续位的作用。
由于MQTT协议最多使用四个字节表示剩余长度,并且最后一个字节的最大值只能是0x7F,而不是0xFF。所以能发送的最大消息长度是256MB,而不是512MB。 -
可变报文头(Variable Header)
主要包含协议名,协议版本,连接标志,心跳间隔时间,连接返回码,主题名等。 -
有效负荷
实际上可以理解为消息的主体。当MQTT发送的消息类型是CONNECT(连接)、PUBLISH(发布)、SUBSCRIBE(订阅)、SUBACK(订阅确认)、UBSUNSCRIBE(取消订阅)时会带有负荷。
MQTT的特性
MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:
- 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合;
- 对负载内容屏蔽的消息传输;
- 使用 TCP/IP 提供网络连接;
- 小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;
- 有三种消息发布服务质量:qos
MQTT消息质量
- “至多一次”,Qos 0: 消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。
- “至少一次”,Qos 1: 确保消息到达,但消息重复可能会发生。
- “只有一次”,Qos 2: 确保消息到达一次。
MQTT遗愿标志
在可变报文头的连接标志位字段(Connect Flags)里面有三个will标志位:Will Flag Will Qos和Retain Flag。这些will字段用于监控客户端与服务器之间的连接状况。
遗愿消息:服务器与客户端通信时,当遇到异常或客户端心跳超时的情况,MQTT服务器会替客户端发布一个will消息。当然如果服务器收到来自客户端的DISCONNECT消息则不会触发wiwll消息的发送。因此will字段可以应用于设备掉线后通知用户的场景。
MQTT KeepAlive连接保活
MQTT客户端可以设置一个心跳间隔时间(keep Alive Timer),表示在每个心跳检测时间内发送一条消息。如果在这个时间周期内,没有业务数据相关的消息,客户端会发送一个PINGREQ消息,相应的,服务器会返回一个PINGRESP消息进行确认。
如果服务器在一个半(1.5)个心跳间隔时间周期内没有收到来自客户端的消息,就会断开与客户端的连接。心跳间隔时间最大值可以设置为18个小时。
MQTT 用户认证
-
应用层:MQTT支持客户标识,用户名和密码认证
客户标识:MQTT客户端可以发送最多65535个字符作为客户标识,一般来说可以使用嵌入式芯片的MAC地址或芯片序列号。
用户名和密码:支持通过CONNECT消息的username和password字段发送用户名和密码。但是由于是用的明文传输,抓包工具很容易就获取。 -
传输层:传输层可以使用TLS,除了加密通讯,还可以使用X509证书来认证设备。
在传输层认证是这样的:MQTT代理在TLS握手成功之后可以继续发送客户端的X509证书来认证设备,如果设备不合法就中断连接。
MQTT 用户数据
MQTT 可以传输如下几种类型数据,JSON数据和十六进制数据是最常用的选择
- 十六进制/二进制
- 字符串
- JSON
- XML