客户端,代理,连接的创建 - MQTT 核心系列: 第三章

客户端,代理,连接的创建 - MQTT 核心系列: 第三章

作者: HiveMQ Team

翻译: 索隆有几把刀

欢迎来到《MQTT 核心系列》的第三章,这个系列一共有十章,用来介绍MQTT的核心特性和概念。在这一章中,我们将讨论MQTT中的角色,客户端和代理,以及当你连接到代理时候可用的一些参数和配置项

在上篇文章中,我们讲述了发布订阅模式是如何工作的,以及它是如何应用在MQTT上的。接下来我们快速回顾下核心概念:

  • 发布订阅模式让消息发送方和消息接受方解耦
  • MQTT使用主题来决定消息应该被投送给谁。一个主题是一个具有层级结构的字符串,它可以被用来过滤和路由消息

在上篇文章中,我们站在高处俯瞰了发布订阅模式和它与传统消息队列的区别。在本文中,我们将把镜头拉近MQTT,仔细了解一些概念:MQTT中的客户端,代理,连接的基础,消息以及参数,和基于对代理了解后的连接创建。

介绍

因为MQTT会让消息发布者和消息订阅者解耦,所以需要代理来处理与客户端之间的连接。在我们深入连接的细节前,让我们先搞清楚客户端和代理是什么意思。

客户端

当我们讨论客户端的时候,我们通常说的是MQTT客户端。消息发布者和消息订阅者都是客户端。消息发布者和消息订阅者的区别在于它们是推送消息还是订阅来接收消息(消息推送和消息订阅可以被同一MQTT客户端实现)。客户端可以是任何一台运行了MQTT包并且连接到MQTT代理的设备(从小型控制机到大型服务器)。例如,客户端可以是非常小的,资源受限的设备,只需要它可以连接无线网络且拥有最小库。客户端也可以是出于测试目的运行图形化MQTT客户端的经典计算机。基本上,任何可以在TCP/IP协议栈上实现MQTT协议的设备都可以作为MQTT客户端。客户端实现MQTT协议非常直接和简单。这也是MQTT协议适用于小型机的原因。MQTT客户端库可以用于多种编程语言,例如,c,c++,java,go等。

代理

上文我们介绍了客户端,那么与之对应的就是代理。代理是在任何发布订阅系统中都是核心。根据具体的实现情况,一个代理可以处理数百万个客户端的并发连接。

代理负责接受消息,过滤消息,把消息准确推送到订阅了对应主题的客户端。代理还持有设置了持久化会话的客户端的会话信息,包括订阅和丢失的信息。代理还负责对客户端的健全和授权。通常,代理是可可拓展的,这有助于自定义鉴权和授权,和后端系统的集成。集成是非常重要的,因为代理通常需要暴露在互联网上,并处理大量的客户端,把消息传递给下游系统。

连接

MQTT协议基于TCP/IP协议。客户端可代理都需要有TPC/IP协议簇。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2K5dL4z-1614179420345)(https://www.hivemq.com/img/blog/mqtt-tcp-ip-stack.png)]

连接通常存在于客户端和代理之间。客户端之间是不直接通讯的。连接建立过程大致如下,首先客户端发送一个CONNECT信息给代理,代理收到消息后会回复一个CONNACT消息和一个状态码。一旦连接建立,代理会保持连接处于开启状态直到客户端发送一个断开连接的消息或者连接中断。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1mCuwbQ-1614179420355)(https://www.hivemq.com/img/blog/connect-flow.gif)]

通过NAT建立连接

在很多使用案例中,客户端会位于使用NAT(network address traslation)的路由器后面,NAT会帮忙把私有网络地址转化为共有网络地址。正如我们前面提到的,客户端会通过发送CONNECT消息来建立连接。因为代理会有一个公共网络地址,并保持连接开放来实现消息的双向接受和发布,所以客户端位于NAT后面是没有问题的。

通过消息初始化连接

现在让我们来看看建立连接的消息格式。为了初始化连接,客户端会发送一个消息给代理。假如CONNECT消息不符合MQTT定义的规范,或者从开启套接字到发送CONNECT消息时间过长,代理会关闭连接。这样能规避一些恶意客户端的攻击。对于MQTT 3,一个正常的连接请求消息格式如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7r2OP6g-1614179420359)(https://www.hivemq.com/img/blog/connect.png)]

对于CONNNECT消息里的一些内容,QMTT库的开发者可能会比使用者更感兴趣。

我们将重点关注于如下内容

ClientId

ClientId标识每一个连接到代理的客户端。代理会用ClientId去标志每一个客户端和这个客户端的状态。因此,对于一个代理而言,每个客户端的ClientId都应该是不同的。在MQTT 3.1.1中 如果你想让代理持有一个状态,你可以发送一个空的ClientId。如果是这样,那么Clean Session这个属性必须被设置为true,不然代理会拒绝这个连接。

Clean Session

Clean Session是告诉代理,客户端是否想建立一个持久化会话。在持久化会话(Clean Session = false)中,代理会存储所有的订阅信息并且为QoS等级为1或者2的客户端保存错过的消息。假如是非持久化会话,那么代理不会存储任何消息,并且会清除掉之前持久化会话状态时存储的信息。

Username/Password

MQTT会发送发送用户名密码来实现客户端的鉴权和授权。然后,如果消息不经过加密或者哈希处理,那么密码就是明文传输。

Will Message

最后通知(或者叫做一眼)是MQTT遗嘱特性的一部分。当客户端不正常断开连接时,此消息会通知其他客户端。当客户端连接时,它可以以MQTT消息或者CONNECT消息内的主题的形式向代理提供最后通知。当客户端非正常断开连接时,代理就会代表这个客户端发送通知。你可在这个系列的第9章更加详细的了解遗嘱特性。

KeepAlive

KeepAlive限定的是当代理和客户端建立连接后,二者相互回应的时间间隔,它以秒为单位。它决定了客户端与代理不发送消息能保持连接的最大时间长度。客户端通常会按照约定往代理发送PING的请求信息,代理会返回一个PONG的应答消息。这种方法能保证双方知道对方是否在线。在这个系列的第十章会具体讲解Keep Alive的功能。

基本上,这就是你对于MQTT3.1.1从客户端往代理建立连接所需要了解的知识了。各个库通常会提供其它的配置项。例如,消息排队存储的具体实现方式。

代理回复CONNACK消息

当代理接受到CONNECT消息后,它有义务回复一个CONNACT消息。

CONNACT消息包含两个信息:

  • 当前会话标志
  • 连接返回码
当前会话标志

会话存在标记告诉客户端代理是否已经具有与客户端之前的交互中可用的持久会话
//todo 这里的话不容易理解 等后面看了再说

连接返回码

CONNACT中的第二个确认标志就是连接返回码。它表示连接是否成功。
连接返回

下面是返回码对应表

返回码意义
0连接成功
1连接失败,协议版本不正确
2连接失败,标识符被拒绝
3连接失败,服务器不可用
4连接失败,用户名或密码错误
5连接失败,没有授权

后话

你可能想知道MQTT是怎么保持连接状态开启的,或者你怎么知道连接断开了,不用担心,我们会在后面的章节中用一整章去探讨这些问题。

MQTT核心系列的第三部分到此结束。我们希望您至少学到了一个有关MQTT的新知识,希望您下周再次加入我们,下周的主题是发布,订阅和退订。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值