物联网核心协议MQTT快速入门1简介

想象一下,我们有几十个不同的设备,它们之间必须交换数据。

这些设备是物联网(IoT)板,上面连接了几十个传感器。我们有以下具有不同处理能力的物联网板。Raspberry Pi 3, Raspberry Pi Model B, Intel Edison, and Intel Joule 570x. 这些板子中的每一块都要能够发送和接收数据。此外,我们希望许多移动设备能够发送和接收数据,其中一些设备运行iOS,另一些运行Android。我们必须与许多编程语言合作。

我们的无线网络有些不可靠,我们有一些高延迟的环境。有些设备的功率比较低,很多设备都是靠电池供电,资源比较匮乏。此外,我们还要注意网络带宽的使用。

我们可以使用HTTP请求,并建立一个发布-订阅模型来交换不同设备之间的数据。然而,有一种协议是专门设计的,它比HTTP 1.1协议更轻巧,在涉及到不可靠的网络和连接断断续续的情况下,它能更好地工作。MQ Telemetry Transport( MQTT )更适合这种情况,在这种情况下,许多设备之间必须通过互联网近乎实时地交换数据,而我们需要消耗尽可能少的网络带宽。

MQTT协议是一种机器对机器(M2M Machine-to-Machine)及物联网连接协议。MQTT是一个轻量级的消息传递协议,它使用基于broker的发布订阅机制。

物联网核心协议MQTT快速入门1简介

了解MQTT协议的便捷场景

MQTT适用于以下需要进行数据交换的应用领域。

  • 资产跟踪和管理
  • 汽车远程信息处理技术
  • 化学检测
  • 环境和交通监测
  • 野战部队自动化
  • 火灾和气体测试
  • 家庭自动化
  • 车载信息娱乐系统 (IVI In-Vehicle Infotainment)
  • 医学
  • 讯息传递
  • 销售点(POS Point of Sale)亭
  • 铁路
  • 无线电频率识别(RFID Radio-Frequency Identification)
  • 监视控制和数据采集(SCADA Supervisory Control and Data Acquisition)
  • 老虎机

综上所述,MQTT被设计成适合支持物联网、M2M、嵌入式和移动应用中的以下典型挑战。

  • 轻量
  • 以最小的数据包分发大量的数据。
  • 支持面向事件的范式,异步双向低延迟推送消息。
  • 轻松地将数据从一个客户端发送至多个客户端。
  • 只要事件发生,就可以监听(面向事件的架构)。
  • 支持一直连接和有时连接的模式。
  • 在不可靠的网络上发布信息,并在脆弱的连接上提供可靠的传输。
  • 与电池供电的设备或需要低功率消耗的设备配合得非常好。
  • 能够实现近乎实时的信息传递。
  • 数据安全和隐私
  • 可扩展,将数据分发到几十万个客户。

使用发布-订阅模式

在深入了解MQTT之前,我们必须先了解发布-订阅模式,也就是pub-sub模式。在publish-sub模式中,发布消息的客户端与接收消息的其他客户端是解耦的。客户端不知道其他客户端的存在。客户端可以发布特定类型的消息,只有对特定类型的消息感兴趣的客户端才会收到发布的消息。

发布-订阅模式需要一个代理,也就是服务器。所有的客户端都与broker建立连接。通过broker发送消息的客户端被称为发布者。broker对接收到的消息进行过滤,并将其分发到对接收到的消息类型感兴趣的客户端。对特定类型的消息感兴趣的客户向经纪人注册的客户被称为订阅者。因此,发布者和订阅者都与经纪人建立了联系。

物联网核心协议MQTT快速入门1简介

消息过滤的工作

broker必须确保订阅者只收到他们感兴趣的消息。在发布-订阅模式中,可以根据不同的标准来过滤消息。我们将重点分析基于话题的过滤 ,也称为基于主题的过滤。

考虑到每条消息都属于一个主题。当发布者请求broker发布消息时,必须同时指定主题和消息。经纪人接收到消息后,将其传递给所有订阅了该消息所属主题的订阅者。

经纪人不需要检查消息的有效载荷就可以将消息传递给相应的订阅者,它只需要检查每一条已经到达并需要过滤的消息的主题,然后再发布给相应的订阅者。

物联网核心协议MQTT快速入门1简介

Raspberry Pi 3板子发布一条消息,以120英尺作为有效载荷,以sensor1/altitude作为主题。发布者,将发布请求发送给broker。broker将消息分发到订阅sensor1/altitude主题的两个客户端:iOS智能手机和Android平板电脑。

英特尔爱迪生板块发布一条消息,以75 F作为有效载荷,以sensor42/temperature作为主题。发布者将发布请求发送给经纪人。经纪人将消息发布给唯一订阅sensor42/temperature主题的客户端:Android平板电脑。这样,Android平板电脑就会收到两条消息。

物联网核心协议MQTT快速入门1简介

客户端、服务器和连接。

MQTT broker被称为MQTT服务器。MQTT客户端可以同时是发布者和订阅者,也就是说,客户端可以向特定的主题发布消息,也可以接收属于客户端订阅的主题的消息。

任何拥有TCP/IP协议栈并能够使用MQTT库的设备都可以成为MQTT客户端,即成为发布者、订阅者或既是发布者又是订阅者。

有许多MQTT服务器可用于最流行的平台,包括Linux、Windows和macOS。我们将使用Eclipse Mosquitto MQTT服务器(http://www.mosquitto.org)。Mosquitto是一个开源的MQTT服务器,具有EPL/EDL许可证,与MQTT 5.0、3.1和3.1.1版本兼容。其他服务器有Erlang MQTT Broker(EMQ),也就是EMQTT (http://www.emqtt.io),以及HiveMQ(http://hivemq.com)等。此外有基于云的MQTT服务器合作,如CloudMQTT(http://www.cloudmqtt.com)。

MQTT服务器是我们之前分析的发布/订阅模型的中心枢纽。MQTT服务器负责对MQTT客户端进行认证和授权,客户端经过认证和授权后就可以成为发布者和/或订阅者。所以,MQTT客户端首先要做的就是与MQTT服务器建立连接。

为了建立连接,MQTT客户端必须向MQTT服务器发送一个CONNECT控制包,该控制包的有效载荷必须包括所有必要的信息,以启动连接并进行认证和授权。MQTT服务器会检查CONNECT包,进行认证和授权,并向客户端发送一个CONNACK控制包的响应,我们了解CONNECT控制包后再详细分析。如果MQTT客户端发送无效的CONNECT控制包,服务器会自动关闭连接。

物联网核心协议MQTT快速入门1简介

在MQTT客户端和MQTT服务器之间建立了成功的连接后,服务器将保持连接的开放性,直到客户端失去连接或向服务器发送DISCONNECT控制包来关闭连接。

CONNECT控制包必须在有效载荷中包含以下字段的值,以及控制包中包含的特殊标志字节的位。我们要了解这些字段和标志的含义,因为当我们使用MQTT工具和MQTT客户端库时,我们将能够指定它们的值。

ClientId : 客户端标识符,也称为客户端ID,是一个字符串,用于标识每个连接到MQTT服务器的MQTT客户端。每个连接到MQTT服务器的客户端必须有一个唯一的ClientId,服务器使用它来标识它所持有的与客户端和服务器之间的MQTT会话有关的状态。如果客户端指定一个空值作为ClientId ,MQTT服务器必须生成一个唯一的ClientId来识别客户端。然而,这种行为取决于为CleanSession字段指定的值。

CleanSession : 清洁会话标志是一个布尔值,它指定了MQTT客户端从MQTT服务器断开连接后再重新连接的情况。如果CleanSession被设置为1或true,客户端就会向MQTT服务器表明,只要网络连接还在,会话就会持续。在MQTT客户端断开与MQTT服务器的连接后,任何与该会话相关的信息都会被丢弃。从同一个MQTT客户端到MQTT服务器的新连接将不会使用前一个会话的数据,而是一个新的清洁会话。如果CleanSession被设置为0或false,我们将使用一个持久的会话。在这种情况下,MQTT服务器会存储MQTT客户端的所有订阅,当MQTT客户端断开连接时,MQTT服务器会存储所有到达的消息,这些消息具有特定的服务质量级别,与MQTT客户端在断开连接时的订阅相匹配。这样一来,当同一个MQTT客户端与MQTT服务器建立新的连接时,MQTT客户端将拥有相同的订阅,并将接收到失去连接时无法接收的所有消息。我们将在后面深入探讨消息的服务质量等级以及它们与clean session标志或persistent session选项的关系。

当clean session标志被设置为0或false时,客户端向服务器表明它想要一个持久会话。我们只需要记住一个干净的会话和一个持久的会话是相反的。

UserName : 如果客户端想要指定一个用户名来向MQTT服务器请求认证和授权,它必须将UserName标志设置为1或true,并为UserName字段指定一个值。

password : 如果客户端要指定密码来请求 MQTT 服务器进行身份验证和授权,则必须将 Password 标志设置为 1 或 true,并为 Password 字段指定一个值。

ProtocolLevel : 协议级别值表示MQTT客户端请求MQTT服务器使用的MQTT协议版本。

KeepAlive : KeepAlive是一个以秒为单位的时间间隔。如果keep alive的值不等于0,MQTT客户端会在KeepAlive指定的时间内向服务器发送控制包。如果MQTT客户端不需要发送任何控制包,它必须向MQTT服务器发送一个PINGREQ控制包,也就是一个ping请求来告诉MQTT服务器客户端连接是活着的。MQTT服务器响应PINGREQ控制包,向MQTT客户端发出PINGRESP响应,即ping响应,告诉MQTT客户端与MQTT服务器的连接是活的。当没有任何这些控制包时,连接就会被关闭。如果keep alive的值为0 ,则关闭keep alive机制。

Will , WillQoS , WillRetain , WillTopic 和 WillMessage : 这些标志和字段允许 MQTT 客户端利用 MQTT 的遗嘱功能。如果 MQTT 客户端将 Will 标志设置为 1 或 true,则表明它希望 MQTT 服务器存储与会话相关联的遗嘱信息。WillQoS标志指定了最后一条WillMessage所需的服务质量,WillRetain标志则表示该messsage在发布时是否必须保留。如果MQTT客户端将Will标志设置为1或true,它必须在WillTopic和WillMessage字段中指定WillMessage的主题和消息。如果MQTT客户端断开或失去与MQTT服务器的连接,MQTT服务器将把WillMessage字段中指定的消息发布到WillTopic字段中指定的主题,并选择服务质量。我们将在后面详细分析这个功能。

MQTT服务器将处理一个有效的CONNECT控制数据包,并将以CONNACK控制数据包作出响应。这个控制包将包括以下标志的值,包含在头中。我们要了解这些标志的含义,因为当我们使用MQTT工具和MQTT客户端库时,我们将能够检索到它们的值。

SessionPresent : 如果MQTT服务器收到的连接请求的CleanSession标志设置为1或true,那么SessionPresent标志的值将为0或false,因为没有存储的会话将被重新使用。如果在连接请求中CleanSession标志被设置为0或false,那么MQTT服务器将使用一个持久会话,如果服务器在之前的连接中为客户端设置了一个持久会话并将其找回,那么SessionPresent标志的值将为1或true。否则,SessionPresent将为0或false。想要使用持久化会话的MQTT客户端可以使用这个标志的值来决定它是否需要请求订阅所需的主题,或者订阅是否已经从持久化会话中恢复。

ReturnCode 。如果授权和认证通过,连接成功建立,ReturnCode的值将为0。否则,返回代码将不同于0,客户端和服务器之间的网络连接将被关闭。下表显示了ReturnCode的可能值及其含义。

返回码的值

0 连接被接受

1 连接被拒绝,因为MQTT服务器不支持MQTT客户端在CONNECT控制包中要求的MQTT协议版本。

2 连接被拒绝,因为指定的ClientId(客户标识符)已被拒绝。

3 连接被拒绝,因为网络连接已经建立,但MQTT服务不可用。

4 由于用户名或密码值不正确,连接被拒绝。

5 由于授权失败,连接被拒绝