学习入门 MQTT 协议原理与应用场景

学习认识 MQTT 协议

掌握学习MQTT协议
本文章学习借鉴于太极创客团队,以表感谢。官网http://www.taichi-maker.com/
在这里插入图片描述



一、MQTT是什么?

MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。以上MQTT(消息队列遥测传输)协议规范中的介绍很好地描述了MQTT的全部含义。它是一种很轻的通讯协议。与HTTP之类的协议相比,MQTT在通过网络传输数据时表现出众。该协议的另一个重要特点是易于在客户端实现。因此,MQTT成为了当今世界上最受欢迎的物联网协议。它已广泛应用于车联网、智能家居、即时聊天应用和工业互联网等领域。目前通过MQTT协议连接的设备已经过亿,这些都得益于MQTT 协议为设备提供了稳定、可靠、易用的通信基础。


1.MQTT版本

目前MQTT主流版本有两个,分别是MQTT3.1.1和MQTT5。MQTT3.1.1是在2014年10月发布的,而MQTT5是在2019年3月发布的。由于MQTT3.1.1与MQTT5的时间相差了将近五年,且MQTT5的发布时间距今不久,因此在本文书写时(2020年10月),MQTT3.1.1仍然主流版本。

  1. MQTT3.1.1是MQTT5的基础,因此掌握了MQTT3.1.1后可以通过进一步学习掌握MQTT5的使用。
  2. 当前多种流行编程语言的MQTT客户端库仍然只支持MQTT3.1.1,而不支持MQTT5。
  3. 目前物联网环境中的大量设备仍然使用MQTT3.1.1协议而不支持MQTT5协议。

如果想要使用MQTT5。那么无需重新学习MQTT5,而只要利用MQTT3.1.1的基础再学习MQTT5的新功能就可以了。

二、MQTT基本原理

在MQTT协议通讯中,有两个最为重要的角色。它们分别是服务端和客户端。首先我们来初步了解一下它们。

1. MQTT服务端

MQTT服务端通常是一台服务器。它是MQTT信息传输的枢纽,负责将MQTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。

2. MQTT客户端

MQTT客户端可以向服务端发布信息,也可以从服务端收取信息。我们把客户端发送信息的行为成为“发布”信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅”信息。“订阅”信息这一操作很像我们在视频网站订阅某一部电视剧。当这部电视剧上新后,视频网站会向订阅了该剧的用户发送信息,告诉他们有新剧上线了。

MQTT主题

刚刚我们在讲解MQTT客户端订阅信息时,使用了用户在视频网站订阅电视剧这个例子。在MQTT通讯中,客户端所订阅的肯定不是一部部电视剧,而是一个个“主题”。MQTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。

服务端是如何通过主题来控制客户端之间的信息通讯,流程如下图所示
在这里插入图片描述
在以上图示中一共有三个MQTT客户端。它们分别是汽车,手机和电脑。MQTT服务端在管理MQTT通讯时使用了“主题”来对信息进行管理的。比如上图所示,假设我们需要利用手机和电脑获取汽车的速度,那么我们首先要利用电脑和手机向MQTT服务器订阅主题“汽车速度”。接下来,当汽车客户端向服务端的“汽车速度”主题发布信息后,服务端就会首先检查以下都有哪些客户端订阅了“汽车速度”这一主题的信息。当它发现订阅了该主题的客户端有一个手机和一个电脑,于是服务端就会将刚刚收到的“汽车速度”信息转发给订阅了该主题的手机和电脑客户端。

MQTT客户端在通讯时,往往角色不是单一的。它既可以作为信息发布者也可以同时作为信息订阅者。如下图所示:

在这里插入图片描述

3. MQTT 发布/订阅 特性

服务端对MQTT信息的接收、储存、处理和发送,客户端在发布和订阅信息时,可以相互独立,且在空间上可以分离,时间上可以异步

相互可独立:

MQTT客户端是一个个独立的个体。它们无需了解彼此的存在,依然可以实现信息交流。比如以上实例中汽车客户端在发布“汽车速度”信息时,汽车客户端本身可以完全不知道有多少个MQTT客户端订阅了“汽车速度”这一主题。而订阅了“汽车速度”主题的手机和电脑客户端也完全不知道彼此的存在。大家只要订阅了“汽车速度”主题,MQTT服务端就会在每次收到新信息时,将信息发送给订阅了“汽车速度”主题的客户端。

空间可分离:

空间分离相对容易理解,MQTT客户端在通讯必要条件是连接到了同一个MQTT通讯网络。这个网络可以是互联网或者局域网。只要客户端联网,无论他们远在天边还是近在眼前,都可以实现彼此间的通讯交流。

时间可异步:

MQTT客户端在发送和接收信息时无需同步。这一特点对物联网设备尤为重要。有时物联网设备会发生意外离线的情况。我们使用以上实例二的场景来作为示例。当我们的汽车在行驶过程中,可能会突然进入隧道,这时汽车可能会断开与MQTT服务端的连接。假设在此时我们的手机客户端向汽车客户端所订阅的“空调温度”主题发布了信息,而汽车恰恰不在线。这时,MQTT服务端可以将“空调温度”主题的新信息保存,待汽车再次上线后,服务端再将“空调温度”信息推送给汽车。

三、MQTT客户端连接服务端

1. 首先MQTT客户端将会向服务端发送连接请求。

该请求实际上是一个包含有连接请求信息的数据包。这个数据包的官方名称为CONNECT。
在这里插入图片描述

2. MQTT服务端收到客户端连接请求后,会向客户端发送连接确认。

同样的,该确认也是一个数据包。这个数据包官方名称为CONNACK。
在这里插入图片描述

2. CONNECT – 连接服务端

在上面的描述中我们看到。MQTT客户端要想连接服务端,首先要向服务端发送CONNECT报文。如果此CONNECT报文的格式或内容不符合MQTT规范,则服务器会拒绝客户端的连接请求。

CONNECT报文内容如下图所示
在这里插入图片描述

MQTT客户端要想连接服务端,首先要向服务端发送CONNECT报文。如果此CONNECT报文的格式或内容不符合MQTT规范,则服务器会拒绝客户端的连接请求。

报文 如上图红框所示这个题数据包

所谓报文就是一个MQTT数据包。这个数据包中可能包含有多个信息。比如以上图片就是描绘了一个CONNECT报文(数据包)的详细内容。

信息 如上图绿色的信息栏的内容

在这个CONNECT报文(数据包)中包含有多个信息。上图左侧栏中的内容是CONNECT报文所包含的信息名称。右侧是信息的具体内容。如上图示例中,此CONNECT报文包含有名称为clientId的信息,该信息的内容是”client-1″。当然,上图只是一个示例,不是所有的CONNECT报文中的clientId信息内容都是”client-1″。

clientId – 客户端ID

ClientId是MQTT客户端的标识。MQTT服务端用该标识来识别客户端。因此ClientId必须是独立的。如果两个MQTT客户端使用相同ClientId标识,服务端会把它们当成同一个客户端来处理。通常ClientId是由一串字符所构成的,如上图所示,此示例中的clientID是“client-1”。

该表示类似与网络IP 一样独立,

cleanSession – 清除会话

为了保证重要的MQTT报文可以被客户端准确无误的收到。在服务端向客户端发送报文后,客户端会向服务端返回一个确认报文。如果服务端没有收到客户端返回的确认报文,那么服务端就会认为刚刚发送给客户端的报文没有被准确无误的送达。在这种情况下,服务端将会执行以下两个操作:

操作1:将尚未被客户端确认的报文保存起来

操作2:再次尝试向客户端发送报文,并且再次等待客户端发来确认信息。

如果cleanSession 被设置为“true”。那么服务端不需要客户端确认收到报文,也不会保存任何报文。在这种情况下,即使客户端错过了服务端发来的报文,也没办法让服务端再次发送报文。其实我们从字面上也很容易理解。cleanSession 的第一个词是clean。这个词的意思是clean(干净)的。服务端一旦发送完报文,就会把报文忘得“干干净净”了。

反过来,如果我们将cleanSession 设置为”false”。那么服务端就知道,后续通讯中,客户端可能会要求我保存没有收到的报文。

从以上的描述不难看出,如果某个客户端用于收发非常重要的信息(比如前文示例中汽车自动驾驶系统),那么该客户端在连接服务端时,应该将cleanSession设置为”false”。这样才能让服务端保存那些没有得到客户端接收确认的信息。以便服务端再次尝试将这些重要信息再次发送给客户端。

相反的,如果某个客户端用于收发不重要的信息(比如前文示例中车载音乐系统)那么该客户端在连接服务端时,应该将cleanSession设置为”true”。

keepAlive – 心跳时间间隔

MQTT服务端运行过程中,当有客户端因为某种原因断开了与服务端的连接,服务端需要实时了解这一情况。KeepAlive (心跳时间间隔)正是用于服务端了解客户端连接情况的。不过关于KeepAlive (心跳时间间隔)目前讲解还为时过早,我们会在后续的课程中给您做详细介绍。目前您只需要记住,KeepAlive用于服务端实时了解客户端是否与其保持连接的情况。

3. CONNACK – 确认连接请求

下图是CONNACK报文所包含的信息内容

在这里插入图片描述

returnCode – 连接返回码

当服务端收到了客户端的连接请求后,会向客户端发送returnCode(连接返回码),用以说明连接情况。如果客户端与服务端成功连接,则返回数字“0”。如果未能成功连接,连接返回码将会是一个非零的数值,具体这个数值的含义,请见下图所示:

在这里插入图片描述

sessionPresent – 当前会话

对于不重要的MQTT客户端,它们在向服务器发送连接请求时,CONNECT报文中的cleanSession通常设置为true。原因是这类不重要的MQTT客户端即使丢失信息也不会影响整体系统运行。因此服务端在看到客户端的cleanSession为true时,就不会保存发送给它们的信息。

然而对于汽车导航系统这类重要的MQTT客户端来说。当它在连接服务端时,cleanSession肯定时设置为false。原因是重要客户端需要服务端确保信息发送准确无误。如果服务端发现发送给重要客户端的信息没有得到确认,会将报文进行保存。

当重要客户端连接服务端时,服务端可能保存着没有得到确认的报文。如果是这样的话,那么客户端在连接服务端时,就会通过sessionPresent来了解服务端是否有之前未能确认的信息。
首先,

当客户端发送的CONNECT报文中的cleanSession设置为true。在这种情况下,客户端是不需要服务端保存任何报文的。那么服务端发送的确认连接CONNACK报文中,sessionPresent肯定是false,也就是说,服务端没有保存任何报文。

当客户端发送的CONNECT报文中的cleanSession设置为false时,客户端是要求服务端保存报文的。在这种情况下,如果服务端的确保存了没有收到客户端接收确认的报文信息,那么cleanSession为true,否则为false。

简言之,CONNACK报文的sessionPresent与CONNECT报文的cleanSession相互配合。其作用是客户端发送连接请求时,服务端告知客户端有没有保存报文信息。这个被服务端保存的报文信息是来自于上一次客户端连接时,服务端曾经发送此报文给客户端,但是发送后没有收到客户端接收确认。

下一节。开始使用MQTT

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闰土小蒋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值