当前位置:首页 > 户外运动 > 正文内容

MQTT(3. MQTT简要介绍)

2023-05-25 22:18:57户外运动1

Mqtt介绍一

MQTT ( 消息队列遥测传输 )是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族 上,是为硬件性能低下的远程设备以及 *** 状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个 消息中间件 。

MQTT(3. MQTT简要介绍)

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的 *** 的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份: 发布者(Publish) 、 *** (Broker) (服务器) 、订阅者(Subscribe) 。其中,消息的发布者和订阅者都是客户端,消息 *** 是服务器,消息发布者可以同时是订阅者。

MQTT传输的消息分为: 主题(Topic)和负载(payload) 两部分:

MQTT服务器以称为"消息 *** "(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:

在MQTT协议中,一个MQTT数据包由: 固定头(Fixed header)、可变头(Variable header)、消息体(payload) 三部分构成。MQTT数据包结构如下:

(1) 固定头(Fixed header) 。存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。

(2) 可变头(Variable header) 。存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。

(3) 消息体(Payload) 。存在于部分MQTT数据包中,表示客户端收到的具体内容。

固定头存在于所有MQTT数据包中,其结构如下:

相于一个4位的无符号值,类型、取值及描述如下

在不使用标识位的消息类型中,标识位被作为保留位。如果收到无效的标志时,接收端必须关闭 *** 连接:

Payload消息 *** MQTT数据包的第三部分,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:

3. MQTT简要介绍

——

[1.MQTT项目工程](https://github.com/LiamBindle/MQTT-C)

[2.MQTT API说明文档](https://liambindle.ca/MQTT-C/group__api.html)

[3.MQTT协议中文版](https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/01-Introction.html)

MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。

MQTT协议通过交换预定义的MQTT控制报文来通信。

报文格式: 固定包头+可变包头+payload。

固定包头: 由两个字节组成

byte1 高四位表示控制报文的类型,低四位表示控制报文类型的标志位。

byte2表示剩余长度,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。

可变包头:

某些MQTT控制报文包含一个可变报头部分。它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标(Packet Identifier)字段存在于在多个类型的报文里。

有效载荷:

对于PUBLISH来说有效载荷就是应用消息。

——1. *** 建立连接后,客户端发送的之一个报文必须是CONNECT报文

——2. 客户端只能发送一次CONNECT 报文,发送两次会当作协议违规处理,并断开连接。

——3. 有效载荷包括:客户端唯一标识符,will主题,will消息,用户名和密码。

——4.可变包头:协议名(protocol name)+协议级别(protocol level)+连接标志(connect flags)+保持连接(keep alive)。

——5. 协议名: MQTT的UTF-8编码的字符串。(MSB+LSB +MQTT 六个字节)

——6. 协议级别:一个字节

——7. 连接标志:一个字节,包含一些用于指定MQTT连接行为的参数。同时还指出有效载荷中的字段是否存在。服务端必须验证CONNECT控制报文的保留标志位(第0位)是否为0,如果不为0必须断开客户端连接。

——8. 清理会话:byte8 的bit1位标志。

这个二进制位指定了会话状态的处理方式。客户端和服务端可以保存会话状态,以支持跨 *** 连接的可靠消息传输。这个标志位用于控

制会话状态的生存时间。

标志设置为0:服务端必须基于当前会话(使用客户端标识符识别)的状态恢复与客户端的通信。

标志设置为1:客户端和服务端必须丢弃之前的任何会话并开始一个新的会话。会话仅持续和 *** 连接同样长的时间。

——9. 遗嘱标志 WILL FLAG: byte8的bit2位标志。

遗嘱标志(Will Flag)被设置为1,表示如果连接请求被接受了,遗嘱(Will Message)消息必须被存储在服务端并且与这个 *** 连接关联。之后 *** 连接关闭时,服务端必须发布这个遗嘱消息,除非服务端收到DISCONNECT报文时删除了这个遗嘱消息。

服务端发送CONNACK报文响应从客户端收到的CONNECT报文。服务端发送给客户端的之一个报文必须是CONNACK。

如果客户端在合理的时间内没有收到服务端的CONNACK报文,客户端应该关闭 *** 连接。合理 的时间取决于应用的类型和通信基础设施。

CONNACK报文没有有效载荷。

PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。

固定包头:

注意byte1的bit3为重发标志DUP。

如果DUP标志被设置为0,表示这是客户端或服务端之一次请求发送这个PUBLISH报文。如果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。

服务端发送PUBLISH报文给订阅者时,收到(入站)的PUBLISH报文的DUP标志的值不会被传播。发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定。

可变包头:

主题名 :topic name

报文标识符 :packet identitfier。

有效载荷 :有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。

响应:PUBLISH报文的接收者必须按照根据PUBLISH报文中的QoS等级发送响应。

PUBACK报文是对QoS 1等级的PUBLISH报文的响应。

PUBACK报文没有有效载荷。

PUBREC报文是对QoS等级2的PUBLISH报文的响应。它是QoS 2等级协议交换的第二个报文。

PUBREC报文没有有效载荷。

PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文。

PUBREL报文没有有效载荷。

PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文。

PUBCOMP报文没有有效载荷。

客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给与那些订阅匹配的主题,服务端发送PUBLISH报文给客户端。SUBSCRIBE报文也(为每个订阅)指定了更大的QoS等级,服务端根据这个发送应用消息给客户端。

有效载荷:

SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合。没有有效载荷的SUBSCRIBE报文是违反协议的。

响应:

服务端收到客户端发送的一个SUBSCRIBE报文时,必须使用SUBACK报文响应,SUBACK报文必须和等待确认的SUBSCRIBE报文有相同的报文标识符。

服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。SUBACK报文包含一个返回码清单,它们指定了SUBSCRIBE请求的每个订阅被授予的更大QoS等级。

有效载荷:

有效载荷包含一个返回码清单。每个返回码对应等待确认的SUBSCRIBE报文中的一个主题过滤器。返回码的顺序必须和SUBSCRIBE报文中主题过滤器的顺序相同。

客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。

有效载荷 :

UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。

UNSUBSCRIBE报文中的主题过滤器必须是连续打包的、按照定义的UTF-8编码字符串

UNSUBSCRIBE报文的有效载荷必须至少包含一个消息过滤器。没有有效载荷的UNSUBSCRIBE报文是违反协议的。

响应:

UNSUBSCRIBE报文提供的主题过滤器(无论是否包含通配符)必须与服务端持有的这个客 户端的当前主题过滤器 *** 逐个字符比较。如果有任何过滤器完全匹配,那么它(服务端)自己的订阅将被删除,否则不会有进一步的处理。

如果服务端删除了一个订阅:

——它必须停止分发任何新消息给这个客户端 []。

——它必须完成分发任何已经开始往客户端发送的QoS 1和QoS 2的消息 []。

——它可以继续发送任何现存的准备分发给客户端的缓存消息。

服务端必须发送UNSUBACK报文响应客户端的UNSUBSCRIBE请求。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符 。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应 。

如果服务端收到包含多个主题过滤器的UNSUBSCRIBE报文,它必须如同收到了一系列的多个UNSUBSCRIBE报文一样处理那个报文,除了将它们的响应合并到一个单独的UNSUBACK报文外。

服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。

UNSUBACK报文没有有效载荷。

客户端发送PINGREQ报文给服务端的。用于:

1. 在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。

2. 请求服务端发送 响应确认它还活着。

3. 使用 *** 以确认 *** 连接没有断开。

保持连接(Keep Alive)处理中用到这个报文。

——PINGREQ报文没有可变报头。

——PINGREQ报文没有有效载荷。

响应:

服务端必须发送 PINGRESP报文响应客户端的PINGREQ报文。

服务端发送PINGRESP报文响应客户端的PINGREQ报文。表示服务端还活着。

保持连接(Keep Alive)处理中用到这个报文。

PINGRESP报文没有可变报头。

PINGRESP报文没有有效载荷。

DISCONNECT报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接。

DISCONNECT报文没有可变报头。

DISCONNECT报文没有有效载荷。

响应:

客户端发送DISCONNECT报文之后:

—— 必须关闭 *** 连接 [MQTT-3.14.4-1]。

——不能通过那个 *** 连接再发送任何控制报文。

服务端在收到DISCONNECT报文时:

——必须丢弃任何与当前连接关联的未发布的遗嘱消息。

——应该关闭 *** 连接,如果客户端 还没有这么做。

为了提供服务质量保证,客户端和服务端有必要存储会话状态。在整个会话期间,客户端和服务端都必须存储会话状态 。会话必须至少持续和它的活跃 *** 连接同样长的时间。服务端的保留消息不是会话状态的组成部分。服务端应该保留那种消息直到客户端删除它。

MQTT协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端 和从服务端到客户端)的字节流。

无连接的 *** 传输协议如UDP是不支持的,因为他们可能会丢失数据包或对数据包重排序。

MQTT按照这里定义的服务质量 (QoS) 等级分发应用消息。分发协议是对称的,在下面的描述中,客户端和服务端既可以是发送者也可以是接收者。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。

qos0:最多分发一次

qos1:至少分发一次

qos2:仅分发一次

客户端设置清理会话(CleanSession)标志为0重连时,客户端和服务端必须使用原始的报文标识符重发任何未确认的PUBLISH报文(如果QoS>0)和PUBREL报文 [MQTT-4.4.0-1]。这是唯一要求客户端或服务端重发消息的情况。

服务端接管入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态。正常情况下,客户端收到发送给它的订阅的消息。客户端也可能收到不是与它的订阅精确匹配的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。正在处理UBSUBSCRIBE请求时也可能收到消息。客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它选择是否处理报文包含的应用消息 。

实现本章定义的协议流程时,客户端必须遵循下列规则:

重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发(适用于QoS 1和QoS 2消息)[MQTT-4.6.0-1]。

——必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS 1消息)。

——必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS 2消息。

——必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS 2消息)。

服务端必须默认认为每个主题都是有序的。它可以提供一个管理功能或其它机制,以允许将一个或多个主题当作是无序的 。

服务端处理发送给有序主题的消息时,必须按照上面的规则将消息分发给每个订阅者。此外,它必须按照从客户端收到的顺序发送PUBLISH报文给消费者(对相同的主题和QoS)。

斜杠(‘/’ U+002F)用于分割主题的每个层级,为主题名提供一个分层结构.

数字标志(‘#’ U+0023)是用于匹配主题中任意层级的通配符。

加号 (‘+’ U+002B) 是只能用于单个主题层级匹配的通配符。

服务端不能将 $ 字符开头的主题名匹配通配符 (#或+) 开头的主题过滤器.

$SYS/ 被广泛用作包含服务器特定信息或控制接口的主题的前缀。

应用不能使用 $ 字符开头的主题。

订阅 “#” 的客户端不会收到任何发布到以 “$” 开头主题的消息。

订阅 “+/monitor/Clients” 的客户端不会收到任何发布到 “$SYS/monitor/Clients” 的消息。

订阅 “$SYS/#” 的客户端会收到发布到以 “$SYS/” 开头主题的消息。

订阅 “$SYS/monitor/+” 的客户端会收到发布到 “$SYS/monitor/Clients” 主题的消息。

如果客户端想同时接受以 “$SYS/” 开头主题的消息和不以 $ 开头主题的消息,它需要同

时订阅 “#” 和 ““$SYS/#”。

除非另有说明,如果服务端或客户端遇到了协议违规的行为,它必须关闭传输这个协议违规控制报文的 *** 连接.

MQTT方案通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些机制:

——用户和设备身份认证

——服务端资源访问授权

——MQTT控制报文和内嵌应用数据的完整性校验

——MQTT控制报文和内嵌应用数据的隐私控制

作为传输层协议,MQTT仅关注消息传输,提供合适的安全功能是实现者的责任。使用TLS[RFC5246] 是比较普遍的选择。

广泛采用高级加密标准 [AES] 数据加密标准 [DES] 。

推荐使用为受限的低端设备特别优化过的轻量级加密国际标准 ISO 29192 [ISO29192] 。

如果MQTT在WebSocket [RFC6455] 连接上传输,必须满足下面的条件:

——MQTT控制报文必须使用WebSocket二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必须关闭 *** 连接 。

——单个WebSocket数据帧可以包含多个或者部分MQTT报文。接收者不能假设MQTT控制报文按WebSocket帧边界对齐 。

——客户端必须将字符串 mqtt 包含在它提供的WebSocket子协议列表里 。

——服务端选择和返回的WebSocket子协议名必须是 。

——用于连接客户端和服务器的WebSocket URI对MQTT协议没有任何影响。

MQTT规范定义了MQTT客户端实现和MQTT服务端实现的一致性要求

MQTT实现可以同时是MQTT客户端和MQTT服务端。接受入站连接和建立到其它服务端的出站连接的服务端必须同时符合MQTT客户端和MQTT服务端的要求 。

为了与任何其它的一致性实现交互操作,一致性实现不能要求使用在本规范之外定义的任何扩展 。

附录:

控制报文类型

byte1:标志位flags:

MQTT简单介绍

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上。好比你给好友发送一封电子邮件,发送完成后你可以去做别的事情,收件人也不必立刻响应,可以在自己有空的时候查看邮件,是一个典型的异步发布/订阅场景。而另一种典型的同步请求/回答场景,可以用接打 *** 的场景来类比。

MQTT的设计遵循以下的原则:

为了满足不同的场景,MQTT支持三种不同级别的服务质量(Quality of Service,QoS)为不同场景提供消息可靠性:

MQTT拥有14种不同的消息类型:

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、 *** (Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息 *** 是服务器,消息发布者可以同时是订阅者。

MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:

MQTT会构建底层 *** 传输:它将建立客户端到服务器的连接,提供两者之间的一个有序的、无损的、基于字节流的双向传输。

当应用数据通过MQTT *** 发送时,MQTT会把与之相关的服务质量(QoS)和主题名(Topic)相关连。

一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的 *** 连接。客户端可以:

MQTT服务器以称为"消息 *** "(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:

订阅包含主题筛选器(Topic Filter)和更大服务质量(QoS)。订阅会与一个会话(Session)关联。一个会话可以包含多个订阅。每一个会话中的每个订阅都有一个不同的主题筛选器。

每个客户端与服务器建立连接后就是一个会话,客户端和服务器之间有状态交互。会话存在于一个 *** 之间,也可能在客户端和服务器之间跨越多个连续的 *** 连接。

连接到一个应用程序消息的标签,该标签与服务器的订阅相匹配。服务器会将消息发送给订阅所匹配标签的每个客户端。

一个对主题名通配符筛选器,在订阅表达式中使用,表示订阅所匹配到的多个主题。

消息订阅者所具体接收的内容。

MQTT协议中定义了一些 *** (也被称为动作),来于表示对确定资源所进行操作。这个资源可以代表预先存在的数据或动态生成数据,这取决于服务器的实现。通常来说,资源指服务器上的文件或输出。主要 *** 有:

MQTT 基本认知

物联网 (internet of thing) ,表示的是可以把一些带某些传感器的设备(终端),接入到互联网的行为。

通过互联网连接这些设备,这些设备就能够互相协作。

而 MQTT 就是这些设备之间数据通信的一个基于 TCP/IP 的协议。

每个终端都和实现了 MQTT 协议的 *** /服务器相连。

通过 published MQTT *** 服务器的某个 主题 发送数据。

通过 subscription 从 MQTT *** 服务器获取自己订阅的 主题 数据。

MQTT 协议是一种轻量级的、灵活的 *** 协议。并且非常适合 IOT 的场景。

大多数开发人员已经熟悉了 HTTP WEB 协议。那么为什么不让 IOT 设置链接到 WEB 服务?

设备可以采用 HTTP 请求的形式发送数据,并采用 HTTP 响应的形式从服务器获取数据,接受更新。

因为对于 IOT 的设备来说,这种 主动请求--> 被动等待应答的 数据传输模型存在严重的局限性:

那么,MQTT 为什么如此轻便且灵活?MQTT 协议的一个关键的特性是 发布/订阅模型 。它将数据的发布者和接受者分离。

一个设备终端既可以是数据的发布者 (published) 也可以是数据的订阅者 (subscription) 。

一个设备如果要发布数据,只需要往 *** 服务器中 相应的主题发布数据内容即可。

一个设备如果需要接受到数据,只需要在 *** 服务器中, 提前订阅自己需要关注的主题即可。

MQTT 最基本的体验,就是使用 mosquitto 。

Mosquitto是一款实现了 MQTT v3.1 协议的开源消息 *** 软件,提供轻量级的,支持发布/订阅的的消息推送模式,使设备对设备之间的短消息通信简单易用。

它可以理解成一个 MQTT 的 *** 服务器。

基本步骤如下:

安装成功截图

使用 brew services start mosquitto 启动 MQTT 服务

运行截图

然后再打开另外两个终端窗口,模拟两个IOT设备。A 订阅 MQTT 服务。B 向 MQTT 的服务发送数据。

A订阅当前MQTT的某个服务。

B向 MQTT 服务器发布(published) 数据。

然后,我们就可以在A控制台里看到由 B 通过 MQTT 服务发送的数据了。

基本流程图

控制台 A 向 MQTT 服务器订阅 dw/demo 服务,并被动的等待 MQTT 服务器返回数据。

控制台 B 主动的向 MQTT 服务器的 dw/demo 服务发送 published 数据,之后。服务器会主动向事先订阅了 dw/demo 的终端分发此消息。

MQTT 是一种链接协议,它指定了如何组织数据字节并通过 TCP/IP *** 传输它们。但实际上,开发人员并不需要链接这个链接协议的具体细节。我们只需要知道,每条消息都有一个命令和数据有效负载。该命令定义消息类型(比如 CONNECT 消息或者 SUB SCRIBE 消息)。所有的 MQTT 库和工具都提供了直接处理这些消息的基本 *** ,并且能自动填充一些必要的字段(在数据包的对应字节填充),比如消息和客户端 ID。

首先客户端发送一条 CONNECT消息 来链接 *** 。CONNECT 消息要求建立从客户端到 *** 服务器的链接。

CONNECT 命令的基本参数

当客户端向 *** 服务器发送一条 CONNECT 命令之后,服务器会调用 CONNACK 命令,告知服务链接的状态。

CONNACK 命令的基本参数

当客户端和服务器建立连接之后,客户端就可以向服务器订阅某些主题的。(发送一条或多条 SUBSCRIBE消息 )。

表明当服务器接受到其他终端推送的此主题数据时,服务器会默认发送给它。

SUBSCRIBE 参数列表

当客户端成功的向服务器订阅某个主题之后,服务器会返回一条 SUBACK 的消息,其中包含一个或者多个 returnCode 参数。

SUBACK消息参数

returnCode : 值 0 - 2 ,表示成功订阅,并返回这个订阅消息的 QOS。值 128 : 订阅失败。

既然客户端可以向服务器订阅某个主题,当然也可以取消订阅。

与 SUBSCRIBE 订阅命令相反的命令是 UNSUBSCRIBE 取消订阅命令。

此命令非常简单。只有一个topic(主题)参数。

上面讲的是订阅,订阅是需要有消息从服务器发送过来的。但是服务器本身基本不产生数据,那数据从何而来呢?

mqtt与socket的区别

mqtt与socket的区别有:

1、mqtt协议是为工作在低带宽、不可靠 *** 的远程传感器和控制设备通讯而设计的协议,而WebSocket则是为了浏览器与服务器全双工通信的一种协议。

2、mqtt是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。Socket是HTML5一种新的协议。

MQTT是一个基于客户端-服务器的消息发布、订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器、通信和物联网。其在智能家居、及一些小型化设备中已广泛使用。

【内部分享】MQTT协议解读及使用经验

时间:2018-07-26

Q: 什么是 *** 连接?

A: *** 连接是传输层定义的概念,在传输层以下只存在 *** 数据包的相互交换。

所谓连接,其实也不是在 *** 上有一条真实存在的数据通道。只要通信双方在一段时间内持续保持数据包交换,就可以视为双方建立的连接并没有断开。

连接的建立是依托于TCP协议的三次握手,一旦连接已经建立完毕,通信双方就可以复用这条虚拟通道进行数据交换。如果连接保持长时间工作一直没有被中断,那么这样的TCP连接就俗称为长连接。

Message Queue Telemetry Transport ,中文直译: 消息队列遥测传输协议 。

在MQTT协议被设计出来的年代,还没有物联网这么时髦的词汇,当年叫做 遥测设备 。

MQTT协议真正开始声名鹊起的原因,是其正好恰恰踩中移动互联网发展的节拍,为消息推送场景提供了一个既简便又具有良好扩展性的现成解决方案。

http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

可以看出,MQTT对消息头的规定十分精简, 固定头部占用空间大小仅为1个字节 ,一个最小的报文占用的空间也 只有两个字节 (带一字节的长度标识位)。

这也是MQTT协议针对不稳定及带宽低下的 *** 环境做出的特定设计 - - - - 尽可能地节省一切不必要的 *** 开销 。

Q:为什么MQTT协议需要心跳报文(PINGREQ, PINGRESP)来维护连接状态,只监控该TCP的连接状态是否可以实现目的?

A: TCP数据传输默认的超时时间过长,不符合应用层上细粒度的要求。

TCP数据传输超时的情况可分成三种: 服务端断开 、 客户端断开 、 中间 *** 断开 。

在前两种场景下,若断开操作是一方主动发起的,即表示为TCP连接正常结束,双方走四次挥手流程;若程序异常结束,则会触发被动断开事件,通信另一方也能立刻感知到本次连接所打开的 Socket 出现中断异常。

唯独中间 *** 的状态是通信双方不能掌握的。 在Linux系统下 ,TCP的连接超时由内核参数来控制,如果通信中的一方没有得到及时回复,默认会主动再尝试 6次 。如果还没有得到及时回应,那么其才会认定本次数据超时。

连带首次发包与六次重试,Linux系统下这7次发包的超时时间分别为 2的0次方 至 2的6次方 ,即1秒、2秒、4秒、8秒、16秒、32秒、64秒,一共127秒。MQTT协议认为如此长的超时时间对应用层而言粒度太大,因此其在应用层上还单独设计属于自身的心跳响应控制。常见的MQTT连接超时多被设定为 60秒 。

扩展知识 - TCP的KeepAlive机制: http://hengyunabc.github.io/why-we-need-heartbeat/

由通信中的 报文标识符 ( Packet Identifier )传达。

Q:仅Publish与Pubrec能保证消息只被投递一次吗?

A: 业务上可以实现,但MQTT协议并没有如此设计,原因如下:

每个消息都会拥有属于自己的报文标识符,但如果需要两次数据交换就实现消息仅只收到一次,就需要通信双方记录下每次使用的报文标识符,并且在处理每一条消息时都需要去重处理,以防消息被重复消费。

但MQTT协议最初被设计的工作对象是轻量级物联设备,为此在协议的设计中报文标识符被约定为 可重用 ,以减少对设备性能的消耗,换回的代价不得不使用四次 *** 数据交换,才能确保消息正好被消费一次。

Q:两个不同客户端在发布与订阅同一Topic下的消息时,都可以提出通信Qos要求,此时以哪项为基准?

A: 伪命题,故意在分享时埋下坑,等人来踩。

两个不同客户端的通信是需要 Broker 进行中转,而不是直连。因此,通信中存在两个不同的会话,双方的Qos要求仅仅作用于它们与 Broker 之间的会话,最终的Qos基准只会向更低要求方看齐。

例:遗嘱消息的正确使用方式可参考此篇文章: https://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament

虽然可以借助 Retain Message 实现绑定一条消息至某个Topic,以达到消息的暂时保留目的。

但首先 Retain Message 并不是为存储场景而设计的,再次MQTT协议并没有对消息的持久化作出规定,也就是说Broker重启后,现有保留消息也将丢失。

Q:两种特殊消息的使用场景?

A: 遗嘱消息,多用于客户端间获取互相之间异常断线的消息通知;

保留消息,可保存 最近一条 广播通知,多用于公告栏信息的发布。

Eclipse Mosquitto :MQTT协议的最小集实现

有 EMQ , HiveMQ , RabbitMQ MQTT Adapter 等。

Qos=2 消息保障的 *** I/O次数过多,如果不是必需,尽少在程序里使用此类消息。

毕竟当初其设计的目的是为了减少设备的性能占用,但若应用场景并不是物联网,而是用于手机、电脑或浏览器端等现在已不缺性能的设备上,更好在报文体中,使用UUID生成全局唯一的消息ID,然后自行在业务解析中判断此报文是否被消费过。

或者,业务方在处理消息时保证其被消费的幂等性,也可消除重复消息对系统带来的影响。

正如MQTT协议并没有依赖TCP连接状态,自己在应用层协议上实现心跳报文来控制连接状态,业务方作为MQTT协议的使用者,也不要完全依赖协议的工作状态,而是依托MQTT协议建立属于业务本身的信息汇报机制,以加强系统的稳健性。

Retain Message 可视为客户端主动拉取的行为。如果业务系统采用 HTTP+MQTT 双协议描述业务过程,主动拉取的操作也可使用 HTTP 请求替代。

作为一个长连接型的应用,上线前需要根据业务量级,评估对操作系统 端口数 与 文件描述符 的占用要求,以防服务器资源被打满。

在服务端的配置文件和客户端的连接参数中,都拥有 max_inflight_messages 此项配置,来维护 Qos=1 or 2 消息是否被成功消费的状态。

MQTT 最初被设计为物联网级的通信协议,因此此参数的默认配额较小(大多数情况下被限制到10至20)。

但如果将MQTT协议应用至手机、PC或Web端的推送场景时,硬件性能已不在是瓶颈,在实际使用中推荐把此参数调大。

Mosquitto提供Bridge功能,需要我们自己配置。

Bridge 意为桥接,当我们把两台Broker桥接在一起时,只需要修改一台Broker的配置,填上另一台Broker的运行地址。前一台Broker将作为客户端发布与订阅后一台Broker的所有Topic,实现消息互通的目的。

桥接带来的问题有以下几点:

我的建议:

Websockets协议被设计的目的是为浏览器提供一个全双工的通信协议,方便实现消息推送功能。

在Websockets协议被设计出来前,受限于HTTP协议的一问一答模型,消息的推送只能靠轮询来实现,在资源消耗与时效性保障上,均难以达到令人满意的效果。

Websockets协议复用了HTTP协议的头部信息,告知浏览器接下来的操作将触发协议升级,然后通信双方继续复用HTTP的Header,但报文内容已转变为双方均接受的新协议的格式。

Websockets协议改进了网页浏览中的消息推送的方式,因此被广泛应用在聊天、支付通知等实时性要求比较高的场合下。

MQTT协议重点在于 消息队列的实现,其对消息投递的方式作出约定,并提供一些额外的通信保障 。

MQTT可采取原生的TCP实现,也有基于Websockets的实现版本。当然后者在 *** 字节的利用率上,不如前者那么精简。但浏览器端无法直接使用TCP协议,所以就只能基于Websockets协议开发。

不过基于Websockets的应用也有方便之处:一是证书不需要额外配置,直接与网站共用一套基础设施;二是可使用 Nginx 等工具管理流量,与普通HTTP流量可共用一套配置 *** 。

MQTT非常适合入门,原因如下:

实际的应用场景远比理想中的复杂,无法一招走遍天下,必须做好取舍。

MQTT协议在这方面做得很优秀,以后工作中可以作为参考,设计好自己负责的业务系统。

Android MQTT 通信

??MQTT 协议 是基于发布/订阅模式的物联网通信协议,凭借简单易实现、支持 QoS、报文小等特点,占据了物联网协议的半壁江山。

??常用于 IOT 物联网和一些需要服务端主动通知客户端的场景。

1. 导入依赖

2. 创建 MqttHelper 辅助类,设置回调监听

3. 连接 MQTT

??连接成功或失败,以及中途的连接掉线,会触发 OnMqttStatusChangeListener 回调

4. MQTT 连接状态监听

5. MQTT 收发消息监听

??onSubMessage 订阅的消息回调,因为存在订阅多个 topic 的情况,所以回调能知道是来自哪个 Topic 的消息;

??onPubMessage 发布的消息回调,用于确认发布的消息是否发送成功。

6. MQTT 订阅 Topic

??需要在 MQTT 连接成功后才能订阅 topic,否则订阅 Topic 不成功,收不到对应消息

7. MQTT 取消订阅 Topic

8. MQTT 发布消息

9. MQTT 断开连接

10. 通知设置

??由于 MQTT 启动了一个 Service,而 Android 8.0 以上对于后台 Service 限制时长 5 秒;所以将 MqttService 绑定到 Notification 上成为了一个前台通知;通知的标题和内容显示可以在 strings.xml 中设置,对应属性如下:

??Android 8.0 及以上开启前台服务绑定到通知,8.0 以下默认不启用,可将 mqtt_foreground_notification_low_26 设为 true,将 8.0 以下设备也开启前台通知服务

??创建 MQTT 实例时需要传送参数 MqttOptions,下面将介绍下部分参数;

1. Topic

??MQTT 是一种发布/订阅的消息协议, 通过设定的主题 Topic,

发布者向 Topic 发送的 payload 负载消息会经过服务器, 转发到所有订阅

该 Topic 的订阅者

?? 通配符 : 假想移动端消息推送场景,有的系统消息是全体用户接收,有的消息是 Android 或 iOS 设备接收, 又或者是某些消息具体推送到用户,当然, 对应的多种类型消息可以通过多订阅几个对应的 Topic 解决,也可以使用通配符;

??通配符有两个, " + " 和 " # ", 与正斜杠 " / " 组合使用;加号只能表示一级Topic, 井号可以表示任意层级 Topic; 例如: 订阅 Topic为 " System/+ ", 发布者发布的 Topic 可以是 System、System/Android、System/iOS; 但是不能是 System/iOS/123, 而订阅的 Topic 如果是" System/# " 则可以收到;

?? 注意,只有订阅的 Topic 才可以使用 通配符, 发布和遗嘱的 Topic 不能包含通配符.

2. ClientID

??发布者和订阅者都是属于客户端, 客户端与服务端建立连接之后,发送的之一个报文消息必须是 Connect 消息,而 Connect 的消息载荷中必须包含 clientID 客户端唯一标识;

??如果两个客户端的 clientID 一样, 则服务端记录之一个客户端连接之后再收到第二个客户端连接请求,则会向一个客户端发送 Disconnect 报文断开连接, 并连接第二个客户端, 而如果此时设置了自动重连, 之一个客户端再次连接,服务端又断开与第二个的连接, 连上之一个客户端, 如此将导致两个客户端不断的被挤掉重连.

??注意: clientID 使用的字符更好是 大小写字母和数字, 长度更好限制在[1, 23] 之间;

3. 遗嘱消息

??可选参数, 客户端没有主动向服务端发起 disconnect 断开连接消息,然而服务端检测到和客户端之间的连接已断开, 此时服务端将该客户端设置的遗嘱消息发送出去

??应用场景: 客户端因 *** 等情况掉线之后, 可以及时通知到所有订阅该遗嘱 Topic 的客户端;

??遗嘱 Topic 中不能存在通配符.

4. Session

??客户端和服务端之间建立的会话状态, 一般用于消息保存, 如果设置清除 Session,则每次客户端和服务端建立连接会创建一个新的会话,之前连接中的消息不能恢复,

??而设置不清除会话, 对应发布者发送的 qos 为 1和2 的消息,还未被订阅者接收确认,则需要保存在会话中, 以便订阅者下次连接可以恢复这些消息;

??注意: Session 存储的消息是保存在内容中的, 所以如果不是重要的消息,更好是设置清除 Session, 或者设置 qos = 0;

5. 心跳包

??标识客户端传输一次控制报文到下一次传输之间允许的空闲时间;在这段时间内,如果客户端没有其他任何报文发送,必须发送一个 PINGREQ 报文到服务器,而如果服务端在 1.5 倍心跳时间内没有收到客户端消息,则会主动断开客户端的连接,发送其遗嘱消息给所有订阅者。而服务端收到 PINGREQ 报文之后,立即返回 PINGRESP 报文给客户端

??心跳时间单位为秒,占用2个字节,更大 2^16 - 1 = 65535秒(18小时12分钟15秒),设置为 0 表示不使用心跳机制; 心跳时间一般设置为几分钟或几十秒即可,时间短点可以更快的发出遗嘱消息通知掉线,但是时间短会增加消息频率,影响服务端并发; 微信长连接为 300 秒,而三大运营商貌似也有个连接时间最小的为 5 分钟。

6. qos

??服务质量等级 qos 对应两部分,一是客户端到服务端发送的消息, 一是服务端到客户端订阅的消息; 从发布者到订阅者实际 qos 为两段路中 qos 最小的。

??qos 可选值 0(最多交付一次)、1(最少交付一次)、2(正好交付一次);

?? qos = 0 :接收方不发送响应,发送方不进行重试;发送方只管发一次,不管是否发成功,也不管接收方是否成功接收,适用于不重要的数据传输;

?? qos = 1 :确保消息至少有一次到达接收方,发送方向接收方发送消息,需要等待接收方返回应答消息,如果发送方在一定时间之内没有收到应答,发送方继续下一次消息发送,直到收到应答消息,删除本地消息缓存,不再发送;所以接收方可能收到1-n次消息;适用于需要收到所有消息,客户端可以处理重复消息。

?? qos = 2 :确保消息只一次到达接收方,发送方和接收方之间消息处理流程最复杂;

?? Mqtt Qos 深度解读 和 MQTT协议QoS2 准确一次送达的实现

7. payload 负载消息

??字节流类型, 是 MQTT 通信传输的真实数据

8. 保留消息

??发布消息时设置, 对应参数 retain, 服务端将保留对应 Topic 最新的一条消息记录; 保留消息的作用是每次客户端连接上线都会收到其 Topic 的最后一条保留消息, 所以可能存在 *** 不稳定,频繁掉线重连,每次重连重复收到保留消息;

?? 可以向对应的 Topic 发送一条 空消息,用于清除保留消息。

MQTT 服务搭建 Apache Apollo 服务器 搭建 MQTT 服务

Github 仓库

mqtt 协议

本网站文章仅供交流学习 ,若来源标注错误或侵犯到您的权益烦请告知,我们将立即删除. 邮箱jdapk@qq.com

分享给朋友:

相关文章

户外春天破冰游戏(户外破冰活动是什么)

户外春天破冰游戏(户外破冰活动是什么)

1. 户外破冰活动是什么“破冰”目的,是打破人际交往间怀疑、猜忌、疏远的藩篱,就像打破严冬厚厚的冰层。破冰是一个专业术语,指的是培训当中一项专业的技术,特别在户外拓展当中,可以说成功的破冰是整个培训是否能达到预期效果的关键。同名还是电影及书籍的名称。破冰的作用是把人与人之间的间隔给消除。2. 室外破...

户外激情徒步登山(户外运动照,徒步登山)

户外激情徒步登山(户外运动照,徒步登山)

1. 户外运动照,徒步登山在登山徒步过程中,中午休息时间较长的午餐食物,通常称为路餐粮。路餐粮以能方便食用与保存的烤馕、面包、火腿肠、榨菜等最为合适。通常路餐粮补充都会选择山顶等风景优美的地点来进行,并可以用CAS炉进行适当加热食用。另外,在户外活动要尽量多带些高热量食物,如水果、巧克力、牛肉干、干...

户外反恐服装排名(反恐作战服)

户外反恐服装排名(反恐作战服)

1. 反恐作战服s1战斗服值100元左右《和平精英》是由腾讯光子工作室群自研打造的的反恐军事竞赛体验类型国产手游,该作于2019年5月8日正式公测。该游戏采用虚幻引擎研发,沿袭端游《绝地求生》的玩法,以及前作《绝地求生:刺激战场》与《绝地求生:全军出击》的运营模式,致力于从画面、地图、射击手感等多个...

亲子户外摄影教程(户外亲子活动照片)

亲子户外摄影教程(户外亲子活动照片)

1. 户外亲子活动照片1宝贝,看到你快乐成长,我们由衷感到:无论我们经历了多少艰辛,都是值得的2.宝贝,你知道吗,因为你,妈妈已改变了许多,妈妈变得很坚强,也变得好脆弱。3.宝贝,无数次看着你熟睡的样子,忍不住狠狠亲你,那是一种无以言表的幸福感觉。4.当我偷偷放开你的手,看你小心地学会了走,你心中不...

户外合适的舞蹈(户外合适的舞蹈有哪些)

户外合适的舞蹈(户外合适的舞蹈有哪些)

1. 户外合适的舞蹈有哪些冬季适合户外跳广场舞,但是要注意以下几方面:1、运动前要热身。运动前的热身,可以避免长时间没有运动,因突然运动造成的拉伤或者运动损伤,运动前 简单活动下膝关节、手关节,扭扭腰。2、运动前不要吃得太饱,因为运动过程中血液循环加快,食物在肠胃里,过多的量容易加重肠胃负担。3、运...

户外求生刀具木柄(户外求生刀是管制刀具吗)

户外求生刀具木柄(户外求生刀是管制刀具吗)

1. 户外求生刀是管制刀具吗  请问在野外携带生存刀是否违法这依具体情况而定,如果是专业人员或者职务原因是可以携带的。   主要依据如下:   1.匕首,除人民解放军和人民警察作为武器、警械配备以外,专业狩猎人员和地质、勘探等野外作业人员必须持有的,须由县以上主管单位出具证明,经县以上公安机关批准,...

户外楼顶隔断(户外楼顶隔断效果图)

户外楼顶隔断(户外楼顶隔断效果图)

1. 户外楼顶隔断效果图可以用比较厚的沥青卷材铺设于屋面作为防水层隔断,国产的沥青卷材质量还可以,它的一面有自粘的作用,施工比较容易,而且价格也比较便宜,是目前作为防水隔断层比较常用的材料。2. 户外顶棚装修效果图对于顶棚和天棚来说,其实是一个意思。顶棚:主要就是家居装饰中的室内的顶部。天棚:是说安...

旅行户外折叠座椅(户外折叠坐垫价格)

旅行户外折叠座椅(户外折叠坐垫价格)

1. 户外折叠坐垫价格那种布叫: 野餐垫又称野餐地毯、多功能毯、坐垫等,用于户外野餐垫,健身垫,爬爬垫,沙滩垫,防潮垫,帐篷底垫等等。【产品类别】休闲用品。【特征】★面料:采用摇粒绒面料,不容易脱毛。★内里:采用复合海绵,质感轻柔舒适。★背面:PVC贴底,防水耐脏。★功能:采用欧美流行一体化折叠设计...

户外硅胶防雨手套(硅胶手套防晒吗)

户外硅胶防雨手套(硅胶手套防晒吗)

1. 硅胶手套防晒吗化妆小物件(安瓶、眼睫毛,这些影楼免费提供的可忽略;或有钱的,将就也请忽略)2、个人用品:硅胶、防晒霜、防晒外衣、平底鞋、安全裤(可根据挑选的婚纱礼服来决定要不要);3、注意贵重物品的保管,注意贵重物品的保管,注意贵重物品的保管,重要的事情说三遍。可以用一个小包装好,并随身携带,...

2.5led户外屏厂家(2.5led户外大屏幕报价)

2.5led户外屏厂家(2.5led户外大屏幕报价)

1. 2.5led户外屏厂家湖南华显电子科技有限公司是一家生产、销售、研发、和安装商用显示设备的高新技术企业,同时也是综合显示系统解决方案提供商,公司位于湖南长沙市--岳麓科技产业园,公司主要产品有液晶拼接屏、超清LED显示屏、液晶广告机、触摸一体机、显示周边设备等,经过多年发展,公司已取得ROHS...