目录
•简介
•MQTT发展历史
•特点
•MQTT 的核心概念
•MQTT 的应用场景
•设计规范
•搭建流程
•安全
•传输模式
•客户端连接
▪连接客户端时的附加参数
▪QoS与Retain
▪Publish发布 / Subscribe订阅
▪Persistent / Clean session 持久/干净会话
•资料来源
简介
•MQTT 全称为 Message Queuing Telemetry Transport(消息队列遥测传输)是一种基于发布/订阅范式的“轻量级”消息协议,由 IBM 发布。
•MQTT 可以被解释为一种低开销,低带宽占用的即时通讯协议,可以用极少的代码和带宽的为连接远程设备提供实时可靠的消息服务,它适用于硬件性能低下的远程设备以及网络状况糟糕的环境下,因此 MQTT 协议在 IoT(Internet of things,物联网),小型设备应用,移动应用等方面有较广泛的应用。
•MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的 发布/订阅型消息协议 ,为此,它需要一个消息中间件。
MQTT发展历史
•IBM公司的安迪·斯坦福-克拉克及Cirrus Link公司的阿兰·尼普于1999年撰写了该协议的第一个版本。
•该协议的可用性取决于该协议的使用环境。IBM公司在2013年就向结构化资讯标准促进组织提交了 MQTT 3.1 版规范,并附有相关章程,以确保只能对规范进行少量更改。MQTT-SN是针对非 TCP/IP 网络上的嵌入式设备主要协议的变种,与此类似的还有ZigBee协议。
•纵观行业的发展历程,“MQTT”中的“MQ” 是来自于IBM的MQ系列消息队列产品线。然而通常队列本身不需要作为标准功能来支持。
•可选协议包含了高级消息队列协议,面向文本的消息传递协议,互联网工程任务组约束应用协议,可扩展消息与存在协议,数据分发服务,OPC UA以及web 应用程序消息传递协议。
•现在MQTT协议已开源
特点
•MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:
•1、MQTT是一种发布/订阅传输协议,基本原理和实现如下。
▪MQTT 协议提供一对多的消息发布,可以解除应用程序耦合,信息冗余小。该协议需要客户端和服务端,而协议中主要有三种身份:发布者(Publisher)、代理(Broker,服务器)、订阅者(Subscriber)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,而消息发布者可以同时是订阅者,实现了生产者与消费者的脱耦。
•2、对负载内容屏蔽的消息传输
▪可以对消息订阅者所接受到的内容有所屏蔽。
•3、使用 TCP/IP 提供网络连接,使用 TCP/IP 提供网络连接,提供有序、无损、双向连接。
▪ MQTT 是一种连接协议,它指定了如何组织数据字节并通过 TCP/IP 网络传输它们。设备联网,也需要连接到互联网中,在大万维的世界中,TCP 如同汽车,有轮子就能用来运输数据,MQTT 就像是交通规则。在网络模型中,TCP是传输层协议,而 MQTT是在应用层,在 TCP 的上层,因此MQTT 也是基于这个而构建的,提高了可靠性。
•4、有三种消息发布服务质量
▪至多一次,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
▪至少一次,确保消息到达,但消息重复可能会发生。
▪只有一次,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果
•5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;
▪ 整体上协议可拆分为:固定头部+可变头部+消息体,这就是为什么在介绍里说它非常适合"在物联网领域,传感器与服务器的通信,信息的收集"。
•6、使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。
▪Last Will:即遗言机制,用于通知同一主题下的其他设备发送遗言的设备已经断开了连接。
▪Testament:遗嘱机制,功能类似于Last Will。
MQTT 的核心概念
•MQTT 的核心概念:
▪Broker(代理服务器、中介):MQTT 系统中负责接收和分发消息的服务器,是 MQTT 系统的核心组件。
▪Publisher(发布者):向 Broker 发布消息的客户端,可以选择一个或多个主题进行消息发布。
▪Subscriber(订阅者):订阅感兴趣的主题,并接收相关消息的客户端。
▪Topic(主题):用来标识消息的分类和结构。Publisher 将消息发布到特定的主题上,Subscriber 订阅特定的主题以接收相关消息。

•一个使用 MQTT 协议的设备、应用程序等,它总是建立到服务器的网络连接。
•可以发布信息,其他客户端可以订阅该信息
•订阅其它客户端发布的消息
•退订或删除应用程序的消息
•断开与服务器连接
•MQTT 服务器称为 Broker(消息代理)也称中介,以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间。
•接受来自客户端的网络连接
•接受客户端发布的应用信息
•处理来自客户端的订阅和退订请求
•向订阅的客户转发应用程序消息
•下面是 MQTT 的消息传递流程的详细步骤:
▪客户端连接:Publisher 或 Subscriber 通过 TCP/IP 连接到 Broker。
▪客户端注册:客户端发送 CONNECT 报文到 Broker,包含客户端的身份认证信息、协议版本号等。
▪会话建立:Broker 接收到 CONNECT 报文后,根据客户端的身份认证信息进行验证,并为客户端创建对应的会话。
▪主题订阅:Subscriber 发送 SUBSCRIBE 报文到 Broker,指定订阅的主题。
▪订阅确认:Broker 收到 SUBSCRIBE 报文后,在订阅列表中将 Subscriber 加入,并返回 SUBACK 报文给 Subscriber。
▪消息发布:Publisher 发送 PUBLISH 报文到 Broker,包含消息的主题和内容。
▪消息分发:Broker 收到 PUBLISH 报文后,根据主题将消息分发给订阅了该主题的所有 Subscriber。
▪消息传递:Subscriber 收到经过分发的消息后,进行相应的处理。
▪客户端断开:客户端发送 DISCONNECT 报文到 Broker,表明断开连接。
MQTT 的数据流
•中介承担着转发 MQTT 通信的服务器的作用。相对而言,发布者和订阅者则起着客户端的作用。
•发布者是负责发送消息的客户端,而订阅者是负责接收消息的客户端。
•MQTT 交换的消息都附带“主题”地址, 各个客户端把这个“主题”视为收信地址,对其执行传输消息的操作。形象地比喻一下,中介就是接收邮件的邮箱。
•中介在等待各个客户端对其进行连接。订阅者连接中介,把自己想订阅的主题名称告诉中介。这就叫作订阅。
•然后发布者连接中介,以主题为收信地址发送消息。这就是发布。
•发布者一发布主题,中介就会把消息传递给订阅了该主题的订阅者。如下图所示。如果订阅者订阅了主题 A,那么只有在发布者发布了主题 A 的情况下,中介才会把消息传递给订阅者。
•订阅者和中介总是处于连接状态,而发布者则只需在发布时建立连接,不过要在短期内数次发布时,就需要保持连接状态了。
•因为中介起着转发消息的作用,所以各个客户端彼此之间没有必要知道对方的 IP 地址等网络上的收信地址。又因为多个客户端可以订阅同一个主题,所以发布者和订阅者是一 对多的关系。
•在设备和服务器的通信中,设备相当于发布者,服务器则相当于订阅者。

•主题采用的是分层结构。用“#”和“+”这样的符号能指定多个主题。如下图图所示,/Sensor/temperature/# 中使用了“#”符号,这样就能指定所有开头为 /Sensor/temperature/ 的主题。此外,/Sensor/+/room1 中使用了符号“+”,这样一来就能指定所有开头是 /Sensor/、结尾是 /room1 的主题。

想了解更多?可以阅读《图解物联网》这本书籍。
MQTT 的应用场景
•一个简单的MQTT的应用场景,具体如下图所示

设计规范
由于物联网的环境是非常特别的,所以MQTT遵循以下设计原则:
(1)精简,不添加可有可无的功能;
(2)发布/订阅(Pub/Sub)模式,方便消息在传感器之间传递;
(3)允许用户动态创建主题,零运维成本;
(4)把传输量降到最低以提高传输效率;
(5)把低带宽、高延迟、不稳定的网络等因素考虑在内;
(6)支持连续的会话控制;
(7)理解客户端计算能力可能很低;
(8)提供服务质量管理;
(9)假设数据不可知,不强求传输数据的类型与格式,保持灵活性。
搭建流程
以PLC和PC的信息交互为例,我们需要一个mqtt服务器(Broker),PLC作为客户端(client)通过mqtt服务器发布(publish)某个主题(topic)的消息(message),PC也作为客户端,连接(connect)到mqtt服务器,且订阅(subscribe)该主题,就能收到消息。
安全
登录序列使用 "ClientID "标识每个客户,然后可选择使用 "用户名 "和 "密码"。如果客户端能力允许,建议将 "ClientID "设置为最能识别客户端的简单字符串。此外,由于支持 SSL/TLS,MQTT 还允许使用客户端 SSL 证书登录。支持带有 x509 证书的 TLS v1.2、v1.1 或 v1.0 协议。值得注意的是,MQTT 协议是纯文本协议,因此如果没有 SSL/TLS,通信将完全不加密(危险主要与传输的密码有关)。一种方法是使用预共享密钥 (PSK),根据各个客户端的身份对其通信进行加密。
•根据所需的通信加密级别,MQTT 协议规定了以下 TCP 通道:
▪1883 = MQTT 未加密传输(unencrypted)--最基本、最常见的 MQTT 通信通道,通信完全未加密(危险主要涉及传输的密码)。因此,不应通过此通道发送敏感数据。
▪8883 = MQTT 加密传输--与 1883 通道不同,这里的数据使用 SSL/TLS 协议加密,因此需要客户端支持才能建立通信。
▪8884 = MQTT 加密 + 客户证书 - 这是一种特殊的最高级别 MQTT 通信安全,因为不仅数据使用 SSL/TLS 协议再次加密,而且客户端还必须提供由代理机构签发的真实性证书。不过,目前只有少数公共代理支持这种通道(例如 Mosquitto - 服务器 "test. mosquitto. org")。

传输模式
MQTT 协议本身只描述了传输信息的结构,但没有定义传输方法。为此,它使用通用的 TCP/IP 协议,即实际上使用通用的本地局域网以太网和全球广域网互联网络。因此,MQTT 协议只构成 OSI 模型的所谓应用层。由于 MQTT 协议的结构非常简单,而且使用通用的以太网通信接口,因此即使在处理器 "小 "的设备上也很容易实现,而且可快速扩展。

客户端连接
首先,客户端(设备、节点)使用 TCP 与代理建立连接。最常用的端口是 1883,TLS 连接的端口是 8883。另一种方法是通过 WebSockets (ws / wss) 连接,通常使用 8080 / 8081 端口(或通过反向代理使用 80 和 443 端口),当然也可以通过任何方式建立通信。

建立连接时,设备会发送 CONNECT 消息,通常会带有一个干净会话标记,以确保从一个 "干净的表 "开始,没有主题被订阅。也可以通过一些基本的名称和密码验证来建立连接。代理将回应一个 CONNACK 消息来确认连接。
随后可能会出现一条或多条 SUBSCRIBE 消息,其中包含设备想要订阅的主题名称。详见上文。代理用 SUBACK 确认。当然,在连接和确认 (CONNACK) 之后的任何时候,设备都可以订阅其他主题。
从连接和确认 (CONNACK) 的那一刻起,一切都已设定,设备和中间商都可以使用 PUBLISH 发送信息。
设备可以使用 UNSUBSCRIBE 消息退订主题(中间商使用 UNSUBACK 消息确认执行),并在完成退订后发送 DISCONNECT 消息。

•Clean Session(清除会话):确定客户端与代理之间已建立的连接是否应为永久连接。如果设置为 "false"(假),所有未从代理处成功传送到客户端的 QoS 1 和 2 消息都将被存储,并在建立下一个连接后转发。如果设置为 "true",代理将不为客户端存储任何报文。
•Last Will - 这是三个可选的 Last Will 主题、Last Will QoS 和 Last Will 消息属性,用于定义主题、消息和关联的 QoS(1 或 2),以防客户端意外断开连接。这可能是由于网络故障、代理问题或“保持活动”属性设置的时间到期。如果发生这种情况,代理上将出现一条定义的消息。该属性通常用于显示客户端状态
•Keep alive 保持在线 - 定义客户端和代理使用 PINGREQ 和 PINGRESP 数据包交换状态信息的时间间隔。
•Return Code 返回代码 - 该标记包含一个返回代码,用于告诉客户端连接尝试是否成功。

•就消息传输本身而言,MQTT协议定义了三个级别的QoS(服务质量)消息确认:
▪在级别0(最多一次,也是即发即忘),发布者向代理发送PUBLISH 消息,并且不担心其他任何事情。代理将以相同的方式将其发送给给定主题的订阅者。
▪在级别1(至少一次),发布者将PUBLISH 消息发送到代理并等待。代理接受消息并将其发送给订阅者(再次发布)。如果设备不支持 QoS1,则将以 QoS 1 或 QoS 0 进行发送。但一般来说,发送时的 QoS 与接收时的 QoS 相同。在这种情况下,它以 QoS1 (PUBLISH) 发送并等待接收方的确认。一旦订阅者确认收到 PUBACK 消息,代理就会删除该消息并将 PUBACK 发送回发布者。发布者知道消息已通过代理并可以删除它。代理可以发送 PUBACK,而无需得到所有接收者的确认。确切的行为取决于实现,大多数情况下都是如此,并且 MQTT 允许两种场景,即等待和不等待。
▪在级别2(正好一次),发布者向代理发送 PUBLISH 消息。与前一种情况一样,发布者收到报文后将其发送给订阅者,并向发布者返回 PUBREC 报文(即确认收到)。发布者回复一条 PUBREL 消息,中间商删除消息并用一条 PUBCOMP 消息确认。至此,交换完成。
•对于 QoS,代理以消息到达的级别发送消息,如果客户端仅知道更低的级别,则可以选择降低级别。

•Retain 保留
▪除了 QoS 外,信息还设置了保留标志,即告诉代理在发送信息后不要将其丢弃,而是将其保存并发送给主题的新订阅者。最后保存的带有保留标记的信息总是要发送的。
•Publish发布
▪如果客户端与代理成功连接,就可以开始发送消息。每条信息都必须包含主题名称、QoS 定义(0-2)、实际信息内容和保留标记。如果我们想在代理服务器上为新连接的客户保留最后一条信息,就需要使用该标记。只有在代理再次接收到信息后,才会根据有序主题发送信息。在这种情况下,新客户将收到最新的信息。
• Subscribe订阅
▪每个主题订阅都必须向代理正确注册。在注册期间,可以使用已经描述的两个通配符。如果我们想为某些主题设置自己的 QoS,我们可以这样做。然后,代理会考虑更高的优先级设置。
▪成功注册一个或多个主题后,根据 QoS 设置和代理内存中可能找到的内容,通过发布功能(订阅)将内容发送到客户端

•如果客户端与提供商之间的连接在会话期间中断,而会话持久性未启用,这些主题就会丢失,客户端必须在重新连接时再次订阅。
•每次连接中断时重新订阅都会给资源有限的客户端造成负担。为了避免这个问题,客户端可以在连接到代理时请求持久会话。持久会话将与客户相关的所有信息都存储在中间商上。客户端在建立连接时提供的客户端标识(clientId)可识别会话。
•持久会话中存储的内容
▪代理在持久会话中存储以下信息(即使客户端处于离线状态)。当客户端重新连接时,这些信息立即可用。
o会话的存在(即使没有订阅)
o所有客户端订阅
o客户端尚未确认的所有 QoS 1-2 消息
o客户端脱机时错过的所有新消息(QoS1-2)
o从客户端收到的尚未完全确认的所有 QoS 2 消息
•如何开始或结束持久会话
▪当客户端连接到代理时,它可以使用 CleanSession 标志请求持久会话:
o当 CleanSession 设置为 true 时,客户端不需要持久会话。每当客户端断开连接时,所有信息和消息都会被删除。
o当 CleanSession 设置为 false 时,代理会为客户端创建持久会话。所有信息和消息都会保留,直到客户端请求干净的会话为止。
▪与代理类似,每个客户端都必须存储一个持久会话。如果客户端请求服务器保留会话数据,则客户端负责存储以下信息
o所有 QoS 1-2 消息: 代理尚未确认的
o所有 QoS 2 消息:从代理收到但尚未完全确认的
资料来源
•MQTT 官方网站 - https://mqtt.org/
•文章 Automatizace.hw.cz - https://automatizace.hw.cz/iot-mqtt-prakticky-v-automatizaci-1dil-uvod.html
•文章 root.cz - https://www.root.cz/clanky/protokol-mqtt-komunikacni-standard-pro-iot/
•HiveMQ - MQTT 专用服务器:客户端、代理/服务器和连接建立 - https://www.hivemq.com/blog/mqtt-essentials-part-3-client-broker-connection-establishment/
•服务质量 0、1 和 2 - https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels/
•持久会话和队列信息 - https://www.hivemq.com/blog/mqtt-essentials-part-7-persistent-session-queuing-messages/