MQTT学习总结

一、概念介绍

        MQTT的全称为Message Queue Telemetry Transport(消息队列遥测传输协议),由IBM公司制定。是一种轻量级的、基于“发布/订阅”模式的消息传输协议

MQTT协议是基于TCP的一个应用层协议

MQTT协议具有以下特性:

  • 基于 TCP 协议的应用层协议;
  • 采用 C/S 架构;
  • 使用订阅/发布模式,将消息的发送方和接受方解耦;
  • 提供 3 种消息的 QoS(Quality of Service): 至多一次(可能会丢包),最少一次(保证包到达,可能会出现重包),只有一次(保证包会到达目的地,且不会出现重包);
  • 收发消息都是异步的,发送方不需要等待接收方应答。

1.MQTT协议的通信模型

        MQTT的通信时通过发布/订阅的方式来实现,订阅和发布又是基于主题(Topic)的。发布方和订阅方通过这种方式来进行解耦,没有直接地连接,需要一个中间方。在MQTT里,中间方称之为Broker,用来进行消息的存储与转发。

1.发布方(Publisher)连接到Broker

2.订阅方(Subscriber)连接到Broker,并订阅主题Topic1

3.发布方(Publisher)发送给Broker一条消息,主题为Topic1

4.Broker收到了发布方的消息,发现订阅方(Subscriber)订阅了Topic1,然后将消息转发给订阅方(Subscriber)

5.订阅方(Subscriber)从Broker接受该数据。

        MQTT通过订阅与发布模型对消息的发布方和订阅方进行解耦后,发布方在发布消息时并不需要订阅方也连接到Broker,只要订阅方之前订阅过相应主题,那么它在连接到Broker之后就可以收到发布方在它离线期间发布的消息。我们可以称这种消息为离线消息。

2.模型角色

Publisher和Subscriber

Publisher和Subscriber是相对于Topic来说的。如果一个Client向某个Topic发布消息,那么这个Client就是Publisher。如果一个Client订阅了某个Topic,那么它就是Subscriber。换句话来说的话,一个Client即可以是发布者,也可以是订阅者

Broker

        MQTT的Broker负责接受发布者的消息,并发送给相应的订阅者,是整个MQTT订阅发布的核心。一般情况下,Broker都是服务器。

Client和Server

        客户端可以是任何终端设备,而服务端大部分情况下都是Broker。

        根据上述描述,这里可以做个简单的总结。比如现在有两个具有联网功能的MCU,这俩就是客户端。然后在远程服务器上搭建一个MQTT服务器,那这个MQTT服务器就是Broker。现在MCU_A对Broker进行订阅Topic,化身为SubscriberMCU_B连接MQTT服务器后,向Topic进行发布消息,化身为Publisher。这样MCU_A就会收到MCU_B发布过来的消息。这时候MCU_A关机了,MCU_B又发布了消息,此时MCU_A肯定是接收不到消息的,因为关机了。此时MCU_B赌气,也关机了。那整个网络中就只剩下Broker了。此时,MCU_A开机,因为之前订阅过了Topic,那Broker检测到MCU_A上线后,就会推送消息给A。这样即使MCU_B不在线,MCU_A也能收到B的离线消息。这个消息是缓存在Broker中。以上过程中,A是订阅者,B是发布者。那这时候如果B也订阅Topic呢?那B即是发布者,也是订阅者。

二、连接与断开

1.MQTT的连接过程

        Client建立到Broker的连接过程如下:

 1.Client发送connect数据包给Broker

2.Broker在收到connect数据包后,给Client返回一个connACK数据包

        connect数据包包含:客户端标识符(Client identifier 唯一的)、用户名(Username)、密码(Password)、遗愿主题(will topic)当client非正常地中断连接时,Broker将会向制定的遗愿主题中发布遗愿消息、遗愿消息(will message)

        connACK数据包包含:连接返回码(Connect Return code)用于标识连接是否建立成功。0标识成功。

2.MQTT断开过程

1.Client主动关闭连接

        client主动关闭连接只需要向Broker发送一个Disconnect数据包就可以了。发送完后,就可以关闭底层的TCP连接了,不需要等待Broker的回复(Broker也不会对Disconnect数据包进行回复)

        为什么Client关闭TCP连接之前,要发送一个和Broker没有交互的数据包,而不是关闭底层的TCP连接?因为涉及到MQTT协议的一个特性。在MQTT协议中,Broker需要判断Client是否是正常的断开连接。当Broker收到Client的Disconnect数据包的时候,Broker则认为Client是正常断开,那么会丢弃当前连接指定的遗愿消息。如果Broker检测到Client连接丢失,但是又没有收到Disconnect数据包,则认为Client是非常断开的,就会向在连接的时候指定的遗愿主题发布遗愿消息。

2.Broker主动关闭连接

        MQTT协议规定Broker在没有收到Client的DISCONNECT数据包之前都应该和Client保持连接。只有当Broker 在Keep Alive的时间间隔内,没有收到Client的任何MQTT数据包的时候会主动关闭连接。一些Broker的实现在MQTT协议上做了一些拓展,支持Client的连接管理,可以主动和某个Client断开连接。

        Broker主动关闭连接之前不会向Client发送任何MQTT数据包,而是直接关闭底层的TCP连接。

3.连接保活(Keep alive)

        Broker需要知道Client是否正常地断开了和它的连接,以发出遗愿消息。实际上Client也需要能够很快的检测它失去了和Broker的连接,以便重新连接。虽然TCP协议在丢失连接时会通知上层应用,但是TCP有一个半打开连接的问题(half-open connection),在这种状态下,一端的TCP连接已经失效,但是另外一端并不知情,它认为连接依然是打开的,它需要很长时间才能感知到对端已经连接断开了,这种情况在使用移动或卫星网络的时候尤为常见。所以仅仅依赖TCP的连接状态是不够的,于是MQTT协议设计了一套Keep alive机制。

        在建立连接的时候,我们可以传递一个Keep alive参数,它的单位是秒。MQTT协议中规定:在1.5倍的Keep alive的时间间隔内,如果Broker没有收到来自Client的任何数据包,那么Broker认为它和Client之间的连接已经断开;同样如果Client没有收到来自Broker的任何数据包,那么Client认为它和Broker之间的连接已经断开。在Broker和Client之间没有任何数据包传输的时候,MQTT中通过PINGREQ/PINGRESP来满足Keep alive的约定和侦测连接状态。

        PINGREQ数据包:当Client在一个Keep alive时间间隔内没有想Broker发送任何数据包,比如Publish和Subscribe的时候,它应该向Broker发送PINGREQ数据包。

        PINGRESP:收到PINGREQ数据包后,会回复一个PINGRESP数据包。

对于Keep alive机制,还需要注意以下几点:

  • 如果在一个Keep Alive时间间隔内,Client和Broker有过数据包传输,比如PUBLISH数据包,Client就没有必要再使用PINGREQ了;
  • Keep Alive值是由Client指定,不同的Client可以指定不同的值;
  • Keep Alive的最大值为18小时12分15秒即65535秒;
  • Keep Alive的值设为0的话,代表不使用Keep Alive机制

三、订阅和发布

1.订阅

1.Client向Broker发送一个Subscriber数据包,该数据包中含有Client想要订阅的主题和其他一些参数。

2.Broker收到Subscribe数据包后,向Client发送一个SubACK数据包作为应答。

Subscribe数据包包含:数据包标识(Packet identifier)两个字节(唯一)、订阅列表(List of Subscriptions)包含Client想要订阅的主题列表,列表中的每项由订阅主题名和对应的QoS组成。

SubACK数据包包含:数据包标识(Packet identifier)两个字节(唯一)、返回码(return codes)包含一组返回码,返回码的数量和顺序和Subscribe数据包的订阅列表对应,用于标识订阅类别中的每一个订阅项的订阅结果。

2.取消订阅

1.Subscriber向Broker发送一个Unsubscribe数据包,该数据包包含想要取消订阅的主题。

2.Broker收到Unsubscribe数据包之后,向Subscirber发送一个UnsubACK数据包作为应答。

Unsubscribe数据包包含:数据包标识(Packet identifier)两个字节(唯一)、主题列表(List of Topics)包含Client想要取消订阅的主题过滤器列表。

UnsubACK数据包包含:数据包标识(Packet identifier)两个字节(唯一)、

3.发布

        MQTT发布中最重要的是Publish数据包,Publish数据包是用于发送方和接收方之间传输消息的。当Publisher要向某个Topic发布一条消息时,Publisher会向Broker发送一个Publish数据包。当Broker要将一条消息转发给订阅了某条主题的Subscriber时,Broker也会向该Subscriber发送一个Publish数据包。接收方会根据数据包中的QoS决定应答,当QoS(Quality of Service)为0时,接收方不做任何应答。

        Publish数据包包含:消息重复标识(DUP flag):当DUP flag=1时,代表该消息是一条重发消息,因接收方没有确认收到之前的消息而重发的(只有在QoS大于0的消息中使用)、QoS、Retain标识:当被设置为1时,Broker应该保存该条消息,当之后有任何新的Subscriber订阅Publish消息中指定的主题时,都会先收到该条消息,这种消息也叫Retained消息、数据包标识(Packet identifier)两个字节(唯一)、主题名称(Topic Name):该消息发布到哪个主题。

文章参考链接:

MQTT系列 | MQTT的基础概念 - 知乎

MQTT系列 | MQTT的连接和断开 - 知乎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值