MQTT 通信协议学习分享



  • 前面的一些故事

    在项目组任务中初次接触到了MQTT的通信协议,觉得非常新鲜有趣,在次做一些分享。其实这个任务早已完成,彼时只是接触了这个模型,但并未接触到实际的应用(典型的传统的用法就不说了),很难想到一个成熟应用模型(商业协议)。最近有公司客户提出mqtt协议的要求,并给了协议文档,于是在此做一个商业模型的分享,作为学习资料。

    MQTT 是物联网众多通信协议里比较著名的一个,现在物联网云平台都提供MQTT的服务,比如阿里云、百度云等,这个协议适用于网络条件不那么稳定的场景,贴切于物联网的应用场景,它是基于订阅和发布的模型,这一点和其他的通信模型有很大不同,这也是它的特点和优势所在,此外它的有效负荷可以非常大,头部的耗费极低。下面将会做一些资料的索引和解析,想详细地讲一讲这个协议,篇幅会较长,会断断续续更下去,不便之处望谅解~

    什么是MQTT?

    Message Queuing Telemetry Transport,消息队列遥测传输
    发展起源
    MQTT 最初由 IBM 于上世纪 90 年代晚期发明和开发。它最初的用途是将石油管道上的传感器与卫星相连接。
    它是一种支持在各方之间异步通信的消息协议。异步消息协议在空间和时间上将消息发送者与接收者分离,因此可以在不可靠的网络环境中进行扩展。使用了一个发布和订阅的模型。

    简要

    MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,因此易于实现。这些特点使得它对很多场景来说都是很好的选择,包括受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT),这些场景要求很小的代码封装或者网络带宽非常昂贵。

    此协议运行在TCP/IP,或其它提供了有序、可靠、双向连接的网络连接上。它有以下特点:

    • 使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。

    • 消息传输不需要知道负载内容。

    • 提供三种等级的服务质量:.

    • “最多一次”,尽操作环境所能提供的最大努力分发消息。消息可能会丢失。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久之后会再次发送。
    • “至少一次”,保证消息可以到达,但是可能会重复。
    • “仅一次”,保证消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。
      很小的传输消耗和协议数据交换,最大限度减少网络流量
    • 异常连接断开发生时,能通知到相关各方。

    三个角色

    • Publisher 发布者(client)
      发布应用消息给其它相关的客户端
    • Subscriber 订阅者 (client)
      订阅以请求接受相关的应用消息,退订以移除接受应用消息的请求
    • Broker 代理服务器 (server)
      接受来自客户端的网络连接
      接受客户端发布的应用消息
      处理客户端的订阅和取消订阅请求
      转发应用消息给符合条件的已订阅客户端
      (发布者和订阅者并不冲突,即对同一客户端发布和订阅可同时存在)

    两个主要业务

    • 发布和订阅
      发布的内容包括主题名(Topic)和消息(message),订阅指定的主题(Topic)即可
      0_1551962540452_ff1414e1-0e55-49ff-b937-1567df62aee8-image.png

    三种服务质量(Quality of Service)

    • QoS_0
      “至多一次”,消息发布完全依赖底层TCP/IP网络,会发生消息丢失或重复。如传感器数据的频繁上报。
      0_1551962621726_6131c7c0-b41f-4e78-a340-d48f1ebce304-image.png

    • QoS_1
      “至少一次”,确保消息到达,但消息重复可能会发生。客户端应具有处理重复消息的能力。
      0_1551962630592_4030dbcb-e37d-4964-8220-c011239b44b9-image.png

    • QoS_2
      “只有一次”,确保消息准确到达一次。应考虑时效性和资源代价。如计费系统、即时通讯类的APP的推送。
      0_1551962636106_ae425f5f-81a9-47a8-b55d-860115d6d1df-image.png

    详解三种服务质量

    • QoS_0
      0_1551962725513_304e7530-51ee-46be-8a6a-a5f08c30ee5a-image.png

    • 此处应有文字详解

    • QoS_1
      0_1551962762648_d179918a-ff8a-4e84-8f1a-7507c6b537a5-image.png

    • 此处应有文字详解

    • QoS_2
      0_1551962787481_e9352d18-2789-4ba6-8af9-b32b7cffdd89-image.png

    • 此处应有文字详解

    • Message ID 和 QoS 降级

    • 此处应有文字详解

    MQTT 通信建立

    0_1551962860932_96d30ff3-07f1-4e9b-8969-def02ee39a3a-image.png

    • 稳定的socket连接
    • 请求连接到服务器(登陆服务器)
    • 发布、订阅、退订
    • 心跳

    MQTT 数据包结构

    • 固定头(Fixed header)
      2~5 byte, 存在于所有MQTT数据包中,表示数据包类型
    • 可变头(Variable header)
      存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容
    • 消息体(Payload)
      存在于部分MQTT数据包中,表示客户端收到的具体内容, 最大(< 268,435,455 byte)
      0_1551962988556_bfd7fd82-680c-4887-9d34-a94bcc14dc0b-image.png

    MQTT连接及其遗嘱

    • “固定头”: 0X10

    • “可变头”:协议名(UTF-8编码)+协议版本1字节+连接的标识符1字节+心跳包时间2字节

    • “有效内容”: “用户ID” +  “临终消息主题” + “临终消息” + “用户名” + “密码”    
      0_1551963059294_fbeec287-8c9a-4f83-b7f4-3641004c80fe-image.png

    • Will Retain:遗嘱保留到服务器,当有新的订阅者出现时,推送该条遗嘱

    • Clean Session:清除会话,当该客户端重新上线时是否继续已有的会话,包括所有订阅的主题

    • 当客户端向服务端发送 DISCONNECT包时,其遗嘱将被丢弃

    MQTT 订阅

    • “固定头”: 0X80

    • “可变头”:Message ID

    • “有效内容”: “消息主题” + “消息” 
      0_1551963170297_cbd8b4d9-fe81-419f-85ae-568cec84c341-image.png

    • 单个订阅包最多一次订阅8个主题

    • 主题树,主题层级分隔符,单/多层分配符,‘/’,‘+’,‘#’,a+(a#)不允许,a/+/b(a/#/b)不允许

    • 大小写敏感

    • 同主题覆盖,与这个主题过滤器匹配的任何现存的保留消息必须被重发

    MQTT 发布

    • “固定头”: 0X11

    • “可变头”:Message ID

    • “有效内容”: “消息主题” + “消息”  
      0_1551963270421_2858bf78-d627-4c83-946f-4fac8d8cf1c6-image.png

    • DUP:该条publish是否是重发的

    • RETAIN:消息保留到服务器,当有新的订阅者出现时,推送该条消息

    • 一次只能发布一个消息

    • Broker为每个主题保留有且只有一条保留消息;

    • 当要清除保留消息时可用同主题空的消息清除,服务端不能存储零字节的保留消息 ,此时在线的客户端将收到该主题的这条消息

    • 发布主题不能包含通配符


    MQTT的一个商用模型

    待续



  • 补上一个很棒的参考文字资料,做mqtt的开发和学习都是非常非常合适的!
    https://github.com/Belief997/mqtt


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

Looks like your connection to Dian was lost, please wait while we try to reconnect.