物联网协议(一)MQTT

文章目录

  • 概念
  • 消息结构
    • 固定头
      • 消息类型
      • 标志位(消息类型的具体标识)
    • 可变头
      • CONNECT
        • 协议名
        • 协议级别
        • 连接标志
        • 保持连接
      • PUBLISH
        • 主题名
        • 报文标识符
        • 保留标志
      • SUBSCRIBE
        • 报文标识符
    • 有效载荷
      • CONNECT
        • 客户端标识符(Client Identifier)
        • Will Topic(遗嘱消息的主题)
        • Will Message(遗嘱消息的内容)
        • User Name(用户名)
        • Password(密码)
      • PUBLISH
      • SUBSCRIBE UNSUBSCRIBE
  • 发布/订阅模型
    • 发布者
    • 订阅者
    • 主题
    • 订阅
    • 发布
    • 遗嘱消息
  • Qos(Quality of Service)
    • Qos0
    • Qos1
    • Qos2

概念

MQTT是一款基于发布订阅模式的轻量级通讯协议,构建于TCP/IP协议之上。应用在有限带宽、低开销和不可靠网络的环境中。
在物联网场景下,MQTT成为连接设备、传递实时数据以及实现设备间协同操作的关键工具。通过发布/订阅模式,设备可以异步地共享信息,网关与服务器之间可以灵活地传递数据,而且MQTT的轻量级设计使得它成为移动设备和传感器等资源有限设备的理想选择。
无论是追踪物流中的货物、监测环境中的传感器数据,还是控制智能家居中的设备,MQTT都以其高效、灵活的特性融入到各种场景中,成为连接物理世界和数字世界的重要纽带。在这个快速发展的数字化时代,MQTT的重要性愈发显著,为我们构建更智能、更互联的未来奠定了坚实的基础。

消息结构

既然MQTT是一个消息协议,那它就会有自己的消息规则,即规定这条消息该以怎样的格式进行传输。
MQTT消息的数据包结构分为固定头、可变头和有效载荷。

固定头

固定头的大小至少为两个字节,第一个字节高4位bit代表消息类型,低四位代表消息类型的具体标识,如DUP重发标识、Qos等级、保留标识等信息,有的消息类型没有;第二个字节标识了可变头和有效载荷的长度。固定头的消息类型代表数据包的类型,比如CONNECT、PUBLISH、SUBSCRIBE等,DUP用来标识是否为重发的消息,Qos定义了消息的服务质量,保留标识位标识服务器是否保留此消息。

消息类型

MQTT定义了多种消息类型,每种类型用于不同的通信场景。以下是MQTT的主要消息类型:

  1. CONNECT(连接):
    • 客户端向服务端发起连接请求,包含连接的各种参数,如协议版本、客户端标识符等。
  2. CONNACK(连接确认):
    • 服务端响应CONNECT消息,通知客户端连接是否成功,并包含连接返回码等信息。
  3. PUBLISH(发布):
    • 用于发布消息,包括发布的主题、消息内容等信息。
  4. PUBACK(发布确认):
    • 用于QoS级别1的消息传递,表示服务端已收到PUBLISH消息。
  5. PUBREC(发布接收,QoS2第一步):
    • 用于QoS级别2的消息传递,表示服务端已收到PUBLISH消息。
  6. PUBREL(发布释放,QoS2第二步):
    • 用于QoS级别2的消息传递,表示客户端已收到PUBREC消息,准备释放消息。
  7. PUBCOMP(发布完成,QoS2第三步):
    • 用于QoS级别2的消息传递,表示服务端已完成消息传递。
  8. SUBSCRIBE(订阅):
    • 客户端向服务端发起订阅请求,指定要订阅的主题和对应的QoS级别。
  9. SUBACK(订阅确认):
    • 服务端响应SUBSCRIBE消息,表示成功订阅,并包含每个订阅的QoS级别。
  10. UNSUBSCRIBE(取消订阅):
  • 客户端向服务端发起取消订阅请求,指定要取消订阅的主题。
  1. UNSUBACK(取消订阅确认):
  • 服务端响应UNSUBSCRIBE消息,表示成功取消订阅。
  1. PINGREQ(PING请求):
  • 客户端向服务端发送PING请求,用于保持连接活跃。
  1. PINGRESP(PING响应):
  • 服务端响应PING请求,表示连接仍然活跃。
  1. DISCONNECT(断开连接):
  • 客户端向服务端发起断开连接请求,正常断开连接时使用。

标志位(消息类型的具体标识)

标志位包括控制消息流的标志,以及质量服务等级(QoS)标志。

  • DUP标志(DUPlicate,重发标志): 该标志位用于指示消息是否为重发的副本。当客户端或服务器需要重新发送消息时,DUP标志被设置为1,以确保消息的正确传递。对于QoS级别1和2的消息,DUP标志用于标识消息是否为重发。
  • QoS标志(Quality of Service,服务质量等级): QoS标志决定了消息传递的服务质量等级,有三个级别:0、1和2。
    • QoS 0:最多一次传递,消息可能会丢失,不保证可靠性。
    • QoS 1:至少一次传递,确保消息至少被传递一次,可能导致消息重复。
    • QoS 2:正好一次传递,确保消息只被传递一次,提供最高的可靠性。
  • Retain标志(保留标识): Retain标志用于指示服务器是否应该保留发布的最后一条消息,以便新订阅者在订阅相应主题时能够接收到最新的消息。当发布者发送消息时,Retain标志被设置为1,以告知服务器要保留这条消息。

可变头

长度可变,根据固定头中的剩余长度字段确定,不同消息类型的可变头内容各不相同。下面列举几种消息类型的可变头:

CONNECT

对于CONNECT消息,可变头包含协议名、协议级别、连接标志、保持连接。

协议名

标识了使用的协议,对于MQTT来说,它是"MQTT",用于确保客户端和服务器都使用相同的协议进行通信。

协议级别

指定了MQTT协议的版本,对于MQTT 3.1.1版本,协议级别的值是4,这有助于确保客户端和服务器使用相同版本的协议进行通信。

连接标志

包含了一系列标志位,用于控制连接的各个方面。
CONNECT消息的连接标志包括:

  • Clean Session(清除会话标志):如果设置为1,表示服务器在客户端断开连接时会删除与客户端相关的所有状态信息。如果设置为0,服务器会保留客户端的状态信息。
  • Will Flag(遗嘱标志):如果设置为1,表示客户端希望发送"遗嘱消息",即在客户端异常断开连接时,服务器将向预定的主题发送一条消息。那么CONNECT的有效载荷里就会包含遗嘱主题、遗嘱消息。
  • Will QoS:指定"遗嘱消息"的服务质量等级。
  • Will Retain:如果设置为1,表示服务器在发布"遗嘱消息"时要保留该消息。
  • Password Flag(密码标志):如果设置为1,表示CONNECT消息包含用户名和密码。
  • User Name Flag(用户名标志):如果设置为1,表示CONNECT消息包含用户名。
保持连接

当使用MQTT协议时,保持连接(Keep Alive)是连接标志的一个重要方面。在CONNECT消息的连接标志中,有一个字段叫做Keep Alive,它表示客户端和服务器之间的保持连接时间间隔。

  • 客户端和服务器之间通过保持连接来确保彼此之间的有效通信。
  • Keep Alive值是以秒为单位的时间间隔。
  • 当客户端与服务器建立连接后,它会在每个Keep Alive间隔内向服务器发送一个PINGREQ消息,以确认连接仍然有效。
  • 如果没有响应PINGRESP报文,则会关闭与服务器的连接,并且如果设置了Will Flag,服务器会向预定的主题发送遗嘱消息。

通过Keep Alive机制,MQTT可以在不断开连接的情况下保持通信链路的有效性。这对于在不稳定的网络环境中保持可靠的通信非常重要,因为它允许及时检测到连接故障并采取相应的措施。

PUBLISH

对于PUBLISH消息,可变头包含主题名、报文标识符(如果QoS级别大于0)、保留标志等。

主题名

表示消息发布的主题,主题是消息的关键标识符,订阅者可以使用主题来过滤感兴趣的消息。

报文标识符

仅在消息的质量服务等级(QoS)大于0时存在,用于确保消息的可靠传递。当QoS级别为1时,PUBLISH消息需要收到对应的PUBACK消息,而在QoS级别为2时,需要收到PUBREC和PUBCOMP两个消息,报文标识符在客户端和服务器之间保证消息传递的有序性和完整性。

保留标志

指定了消息在服务器上的保留策略,如果保留标志被设置为1,表示服务器应该保留最后一条与该主题相关的消息,以便新订阅者在订阅该主题时能够收到最新的保留消息。保留消息是一种特殊的消息,它会一直存储在服务器上,直到被替代为止。

SUBSCRIBE

对于SUBSCRIBE消息,可变头主要包含报文标识符

报文标识符

与PUBLISH消息一样,用于确保消息的可靠传递。在订阅后,服务器会使用这个标识符来标识和关联订阅确认消息(SUBACK)(将SUBSCRIBE消息与SUBACK(订阅确认)进行匹配)。

有效载荷

包含实际的消息内容。下面列举几种消息类型的有效载荷:

CONNECT

客户端标识符(Client Identifier)

每个连接到MQTT服务器的客户端都必须有一个唯一的客户端标识符。客户端标识符用于在服务器端标识和管理连接。它是CONNECT消息的有效载荷中的一个必需字段。

Will Topic(遗嘱消息的主题)

如果CONNECT消息的Will Flag被设置为1,表示客户端希望发送"遗嘱消息",则需要提供Will Topic。
Will Topic是遗嘱消息将要发布的主题。

Will Message(遗嘱消息的内容)

如果CONNECT消息的Will Flag被设置为1,表示客户端希望发送"遗嘱消息",则需要提供Will Message。
Will Message是遗嘱消息的实际内容。

User Name(用户名)

如果CONNECT消息的User Name Flag被设置为1,表示CONNECT消息包含用户名,则需要提供用户名。

Password(密码)

如果CONNECT消息的Password Flag被设置为1,表示CONNECT消息包含密码,则需要提供密码。

PUBLISH

PUBLISH的有效负荷包含要发布的信息,并且该消息的接收者必须按照PUBLISH固定头的Qos等级发送响应

SUBSCRIBE UNSUBSCRIBE

包含订阅和取消订阅的主题和Qos等级。

发布/订阅模型

MQTT采用发布/订阅模式(Publish/Subscribe),这是一种消息传递模型,其中消息的生产者称为发布者(Publisher),而消息的消费者称为订阅者(Subscriber)。
物联网协议(一)MQTT_第1张图片
例如在一个物联网场景下,物联网设备网关内部会有一个MQTT Client(数据包转发器,采用MQTT协议),这时网络服务器(相应的物联网协议对应的网络服务器)充当一个MQTT Broker,网关接收到感应器数据后,将数据加密后发布到相应的MQTT Topic(会与Device EUI相关联)上,我们的应用服务器便可在网络服务器的MQTT Broker上根据Topic(注意这里的Topic与网关下发到网络服务器的Topic不一样,由于网关的数据是加密的,这Topic上是处理过后的数据)订阅(可通过通配符同时订阅多个感应器数据)需要的感应器数据。

发布者

发布者是消息的生产者,负责产生和发布消息。发布者将消息发送到特定的主题(Topic),主题是消息的标识符,用于描述消息的内容或用途。

订阅者

订阅者是消息的消费者,负责接收和处理消息。订阅者通过订阅特定的主题表达对消息的兴趣,只有订阅了某个主题的订阅者才会收到与该主题相关的消息。

主题

主题是消息的逻辑通道,用于将消息分类或标识。发布者发布消息时将其发送到特定的主题,而订阅者则通过订阅特定主题来表达对消息的兴趣。主题的层次结构允许灵活的消息过滤和定制化订阅。

订阅

订阅者通过向MQTT服务器发送订阅请求,表达对特定主题的兴趣。订阅后,订阅者将开始接收与其订阅主题相关的消息。

发布

发布者通过向MQTT服务器发送发布请求,将消息发布到特定主题。发布消息后,所有订阅了相同主题的订阅者都会收到该消息。

遗嘱消息

发布者可以设置遗嘱消息,即在发布者异常断开连接时,服务器会向预定的主题发送预定义的消息。遗嘱消息是在建立连接时设置的,用于处理连接中断的情况。

Qos(Quality of Service)

Qos是消息服务质量等级,用于保障消息的传达。
Qos分为:

Qos0

最多一次,发送者只发送一次PUBLISH报文给接收者,无论接收者是否真的收到,依赖于底层TCP的重传;
物联网协议(一)MQTT_第2张图片

Qos1

至少一次,发送端向接收端发送一个带有数据的PUBLISH包,并在本地保存这个包,接收端收到这个包后,会发送一条确认报文PUBACK给发送端,PUBACK数据包没有消息体(Payload),在可变头中有一个包标识(Packet Identifier),和它收到的PUBLISH包中的Packet Identifier一致。如果发送端收到了这条PUBACK确认报文,根据PUBACK包中的Packet Identifier找到本地保存的PUBLISH包,然后丢弃掉,一次消息的发送完成。如果发送端没有收到PUBACK报文,那么它将PUBLISH包的DUP标识设为1(代表是重新发送的PUBLISH包),重新发送该PUBLISH包。接收端可能会收到重复的消息。
物联网协议(一)MQTT_第3张图片

Qos2

正好一次,发送端发送Qos为2的PUBLISH数据包给接收端,并且在本地保存一份,接收端回复PUBACK确认报文,并在本地也保存一份 PUBLISH 包,当Sender收到PUBREC,它就可以安全的丢弃掉初始Packet Identifier的PUBLISH数据包,同时保存该PUBREC包,并且返回PUBREL报文作为应答,当接收端收到PUBREL报文后,会应答发送端一条PUBCOMP报文,Sender收到PUBCOMP包,那么认为传输已完成,则丢掉对应的PUBREC数据包。至此,一次QoS2的MQTT消息传输就结束了。
物联网协议(一)MQTT_第4张图片

Receiver可能会收到多个重复的PUBLISH包,更加完善的处理如下:
Receiver在收到PUBLISH数据包之后,马上回复一个PUBREC数据包。并会在本地保存PUBLISH包的Packet Identifier,不管之后因为重传多少次这个Packet Identifier的数据包,Receiver都认为是重复的,丢弃。Receiver接收到QoS为2的PUBLISH数据包后,并不马上投递给上层,而是在本地做持久化,将消息保存起来(这里需要是持久化而不是保存在内存)。

Receiver收到PUBREL数据包后,正式将消息递交给上层应用层,投递之后销毁Packet Identifier,并发送PUBCOMP数据包,销毁之前的持久化消息。之后不管接收到多少个PUBREL数据包,因为没有Packet Identifier,直接回复PUBCOMP数据包即可

  • PUBREC消息的发送是为了确认消息已经成功接收,防止重复传递。
  • PUBREL消息的发送是为了告知Broker可以释放之前保留的资源,准备最终的消息传递。
  • PUBCOMP消息的发送是为了确认消息已经被正确处理,防止重复传递。

你可能感兴趣的:(物联网,iot,网络协议,网络)