草庐IT

MQTT协议基本流程、原理

Nimrod__ 2023-12-12 原文

基本概念

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

MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

现在基本上在IoT环境中都是使用的MQTT协议。

在MQTT协议中的一些关键词和基本概念

订阅 Subscription

订阅包含一个主体过滤器(Topic Filter)和一个最大的服务质量(Qos)等级。订阅和单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。

主题名 Topic Name

附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。

主题过滤器 Topic Filter

订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。

会话 Session

客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。

控制报文 MQTT Control Packet

通过网络连接发送的信息数据包。类似于ICMP,MQTT规范定义了十四种不同类型的控制报文,其中一个(PUBLISH报文)用于传输应用消息。

服务器 Broker

在消息订阅模型中充当服务器的角色, 类似于送信的邮差。

Qos 消息服务质量机制

通过使用Qos机制,来保证通信的质量,也就是发送connect报文的次数时间,有以下几种情况:

  1. QoS0: “至多1次”
    消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。1次发送失败后,不再重新发送。
    这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了

  2. QoS1:“至少1次”
    确保信息到达,发送1次对方没有确认接收后,会重新发送,但是可能会出现多次接收的情况

  3. QoS2:“至多一次”
    确保信息到达1次且仅到达1次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到1次。

对于QoS值的确认,是基于二者客户端的的最低值,例如A 客户端使用的是QoS2,B客户端使用的是QoS1,那么服务器最后使用的就是QoS1。

MQTT协议中的方法

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

MQTT协议中的通信过程

建立连接

在建立连接时,首先客户端往服务器发送CONNECT连接建立报文。
规定在网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文。

在一个网络连接上,客户端只能发送一次CONNECT报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接。在这个报文中包含了遗嘱信息、keep alive等标志位

在服务器接收到CONNECT报文后,服务端发送CONNACK报文响应从客户端收到的CONNECT报文。服务端发送给客户端的第一个报文必须是CONNACK。

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

在CONNACK报文中,主要包含连接确认标志和返回码,但是不包含有效载荷

具体见流程图:

发送信息流程

在发送信息的流程中主要有几种报文:
PUBLISH – 发布消息:

PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。在信息中主要的标志位是DUP(重发标志位)、QoS(服务质量标识)、Topic Nmae(主题名)等。
有了PUBLISH报文后,就可以发送QoS为0的报文:
对于QoS为0的情况,发起方在发送PUBLIC 报文后便由Broker发送给接收方,中间不再做任何处理。

对于QoS为1的报文,还需要另外1个报文类型参与

PUBACK –发布确认:

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

有了PUBACK报文后,就可以完成QoS为1 的报文发送。

对于QoS为1的情况,发起方在发送PUBLIC 报文后便由Broker发送给接收方,接收方收到后,会回复PUBACK报文,具体流程如图:

要实现QoS为2的信息发布,还需要另外3个报文:
PUBREC – 发布收到(QoS 2,第一步)

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

PUBREL – 发布释放(QoS 2,第二步)

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

PUBCOMP – 发布完成(QoS 2,第三步)

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

对于QoS为2的信息发布,需要:

  1. 发送方发送PUBLIC报文
  2. 接收方接收到PUBLIC后回复PUBREC报文
  3. 发送方接收到PUBREC报文回复PUBREL报文
  4. 接收方接收到PUBREL后回复PUBCOMP报文

结束。
对于QoS为2的流程,明显多了几个步骤,因此对于该类型的信息发布有较多的流量消耗
具体流程见图:

消息订阅流程

订阅相关报文:
SUBSCRIBE - 订阅主题

客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。
每个订阅注册客户端关心的一个或多个主题。

SUBSCRIBE报文也(为每个订阅)指定了最大的QoS等级,服务端根据QoS等级发送应用消息给客户端。

其主题相关数据放在了有效载荷上,并且还包含一个主题过滤器列表。

SUBACK – 订阅确认

在接收到SUBCRIBE报文后,服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。
SUBACK报文包含一个返回码清单,允许的返回码值:

  • 0x00 - 最大QoS 0
  • 0x01 - 成功 – 最大QoS 1
  • 0x02 - 成功 – 最大 QoS 2
  • 0x80 - Failure 失败
    它们指定了SUBSCRIBE请求的每个订阅被授予的最大QoS等级。

订阅完成后客户端需要传输对应的信息时,会在信息上添加上主题,添加后通过PUBLIC 发送到服务端,服务端再根据主题与订阅情况发送给对应的客户端。

基于以上两个报文,订阅的流程如下:

同样的,有了订阅流程便还有取消订阅流程,相关的有两个报文:
UNSUBSCRIBE –取消订阅

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

关于想要取消的订阅主题列表在有效载荷中,且规定取消订阅主题必须至少包含1个取消订阅主题。

UNSUBACK – 取消订阅确认

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

对于取消订阅确认报文,没有有效载荷。
流程跟订阅类似:


参考资料:
MQTT官方文档

有关MQTT协议基本流程、原理的更多相关文章

  1. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  2. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  3. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  4. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  5. ruby-on-rails - Rails 基本 Base64 身份验证 - 2

    我正在尝试复制此GETcurl请求:curl-D--XGET-H"Authorization:BasicdGVzdEB0YXByZXNlYXJjaC5jb206NGMzMTg2Mjg4YWUyM2ZkOTY2MWNiNWRmY2NlMTkzMGU="-H"Content-Type:application/json"http://staging.example.com/api/v1/campaigns在Ruby中,通过电子邮件+apikey生成身份验证:auth="Basic"+Base64::encode64("test@example.com:4c3186288ae23fd9661c

  6. ruby - HTTP POST 上的 SSL 错误(未知协议(protocol)) - 2

    尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify

  7. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  8. Simulink方法总结和避坑指南(一)——Simulink入门与基本调试方法 - 2

    文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景  最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。  在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记

  9. ruby-on-rails - Rails 和 MQTT : Subscribe to topic in background at server startup? - 2

    我想在服务器启动时在我的Rails应用程序中订阅一个mqtt主题,并保持订阅始终处于事件状态和运行状态。我正在使用这个mqttgem进行mqtt通信:https://github.com/njh/ruby-mqtt这是我现在拥有的:在application.rb中:config.after_initializedomqttSub=BackgroundMQTT.newmqttSub.runend后台MQTT类:classMQTTSubscriberdefrunThread.newdoMQTT::Client.connect(:host=>'localhost',:port=>1883,)

  10. ruby - 是否有 Rack::Session::Cookie 用法的基本示例? - 2

    我找不到任何使用Rack::Session::Cookie的简单示例,并且希望能够将信息存储在cookie中,并在以后的请求中访问它并让它过期.这些是我能找到的唯一示例:HowdoIset/getsessionvarsinaRackapp?http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html这是我得到的:useRack::Session::Cookie,:key=>'rack.session',:domain=>'foo.com',:path=>'/',:expire_after=>2592000,:secret=

随机推荐