• MQTT协议------上


    目录

    前言

    客户端&服务器 

    MQTT控制报文 

    MQTT控制报文由三部分组成 

    固定报头 Fixed header

     剩余长度 Remaining Length

     服务质量等级和协议流程

    MQTT控制报文

    CONNECT – 连接服务端

     固定报头 Fixed header

     可变报头 Variable header

    ​编辑 有效载荷 Payload

    CONNACK – 确认连接请求

    固定报头

    可变报头 (两个字节)

    PUBLISH – 发布消息

    固定报头

    可变报头

    有效载荷 

    响应

    PUBACK –发布确认

    固定报头

    可变报头

     有效载荷

    SUBSCRIBE - 订阅主题

    固定报头

    可变报头 

    有效载荷 

     响应

    SUBACK – 订阅确认

    固定报头

    可变报头 

    有效载荷 

    UNSUBSCRIBE –取消订阅 

    固定报头

    可变报头 

    有效载荷 

    UNSUBACK – 取消订阅确认

    固定报头

    可变报头 

    有效载荷 

    PINGREQ – 心跳请求

    固定报头

    PINGRESP – 心跳响应

    固定报头

    DISCONNECT –断开连接 

     响应


    前言

    不论我们使用哪种互联网接入方式,只要我们的设备可以通过UDP或TCP通信访问互联网上对应IP地址的主机
    那么理论上,当设备与云服务器建立UDP/TCP通信后,只要按照云服务器所规定的通信协议(数据格式)发送/接收消息,我们的设备就能接入云平台,实现物联网。

    【MQTT 】,就是一种通信协议(数据格式协议)。【百度云】【阿里云】【腾讯云】的物联网组件都支持MQTT协议。
    特点:
    ①、"轻量级"通信协议:实现MQTT协议的开销比较小,无需太多的额外数据/文本。
    ②、基于TCP/IP协议:建立TCP连接后,【云下设备】/【云平台】按照MQTT协议规定的数据格式来通信。(属于应用层)
    ③、基于【客户端-服务端】模式:云下设备==客户端、云平台==服务端
    ④、基于【消息发布(PUBLISH)】/【消息订阅(SUBSCRIBE)】模式

    【发布(PUBLISH)】/【订阅(SUBSCRIBE)】

    【请求 /回答】模式:假设你要打电话给朋友,你需要等到朋友接电话了,你们才能够开始交流。
    【发布/订阅】模式:假设你要发邮件给朋友,邮件点击发送后,你就不用管了。
    邮件服务器会将邮件发送给你的朋友,朋友收到新邮件提醒后,任何时候查看邮件都可以。(间接联系)
    与【请求/回答】(例如HTTP)这种同步模式不同,【发布/订阅】模式解耦了发布消息的客户(发布者)与订阅消息的客户(订阅者)之间的关系。
    这意味着【发布者】和【订阅者】之间并不需要直接建立联系。

    客户端&服务器 

    客户端A发布这个主题后也可以订阅这个主题 客户端A,B,C是可以进行通信的,但是在网络连接上客户端A,B,C只和MQTT服务端建立网络连接,通过MQTT服务端来将消息转发

    MQTT 控制报文中的文本字段编码为UTF-8格式的字符串。UTF-8 [RFC3629]是一个高效的Unicode字符编码格式,为了支持基于文本的通信﹐它对ASCII字符的编码做了优化·建议大家尽量发送【标准ASCII码字符串】

    MQTT控制报文 

    MQTT协议通过交换预定义的MQTT控制报文来通信

    MQTT协议规定大部分通信规则,但是有一些通信规则没有规定,交由MQTT服务端(云平台来规定)
    比如:用户名/密码的位数、发布消息的有效载荷格式(纯文本 / JSON /…)客户端订阅的最大主题数量 /
    【百度云】、【阿里云】、【腾讯云】支持 【Qos=0/Qos=1】,不支持 【Qos=2】
    留意【剩余长度】、【字符串前级】、【主题】、【Qos】、【遗嘱】。。。等参数

     下面这三个只有在QoS等于2的时候使用

    PUBREC       5         两个方向都允许    发布收到(保证交付第一步)

    PUBREL        6        两个方向都允许    发布释放(保证交付第二步)

    PUBCOMP    7        两个方向都允许    QoS 2消息发布完成(保证交互第三步)

    MQTT控制报文由三部分组成 

    固定报头 Fixed header

     第一个字节的高四位MQTT控制报文的类型,也就是MQTT控制报文的值

    第一个字节的低四位用于指定控制报文类型的标志位,除了发布消息这个控制报文之外,别的控制报文都是固定的

     从第二个字节开始是剩余长度

     剩余长度 Remaining Length

    剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据也即是说我们只有知道剩余长度,我们才能知道这个MQTT的报文是到哪里结束剩余长度不包括用于编码剩余长度字段本身的字节数。也就是说剩余长度的字节数只是可变报头和有效负载的长度,不包括他自己本身

    剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面 的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个 字节可以编码128个数值和一个延续位(continuation bit)。剩余长度字段最大4个字节。

    它的第一个字节的低7位就是65,因为他之后还有第二个字节,所以说第一个字节它的最高位应该置一,第一个字节就是65+128=193。第二个字节是2,他是小于128的 可以使用7位数据来编码

     MQTT控制报文中的可变报头,有效载荷我们以具体的MQTT控制报文来讲,在介绍MQTT控制报文之前,我们需要先了解一下服务质量等级和协议流程

     服务质量等级和协议流程

    的消息质量等级

    QoS只能等于0,1,2  

    当QoS等于0的时候,表示这个消息最多发送一次,发送方发送了消息,接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没送达

    QoS 等于1的时候: 表示这个消息至少发送一次,发送方发送了这个消息,他需要等待接收方应答,如果接收方没有应答,发送方会尝试再次发送这个消息,那么这个消息至少发送了一次

    QoS 等于2的时候:表示这个消息仅分发一次,他使用下面三个控制报文来实现仅分发一次

    注意:

    MQTT控制报文

    CONNECT – 连接服务端

     客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文

     固定报头 Fixed header

    CONNECT报文的固定报头的第一个字节高四位必须是数值1来表示当前报文是connect报文,第一个字节的低四位是保留位0,从第二个字节开始是剩余长度字段

     

     可变报头 Variable header

    CONNECT报文的可变报头按下列次序包含四个字段:协议名(Protocol Name)协议级别 (Protocol Level)连接标志(Connect Flags)保持连接(Keep Alive)

     注意所有的字符串前都要加上两个字节的前缀来表示字符串的长度

    对于3.1.1版协议,协议级别字段的值是 4(0x04) 

    连接标志 Connect Flags(一个字节)  重要!!!

    连接标志字节包含一些用于指定MQTT连接行为的参数

     

     如果清理会话(CleanSession)标志被设置为0,服务端必须基于当前会话(使用客户端标识 符识别)的状态恢复与客户端的通信,也就是说如果客户端向服务端发送了一个connect报文,并且它的会话清理标志位是0,那么服务端必须恢复和他之前会话的状态,比如客户端的订阅信息,即将传输给客户端的QoS 1和QoS 2级别的消息等等

    如果清理会话(CleanSession)标志被设置为1,客户端和服务端必须丢弃之前的任何会话并 开始一个新的会话。会话仅持续和网络连接同样长的时间,网络连接断开的话,那么这个会话也就结束了。

    遗嘱标志 Will Flag

    位置:连接标志的第2位。

    如果一个设备创建了遗嘱消息的话,如果它从MQTT服务端异常断开的话,MQTT服务端就会将这个设备的遗嘱消息分发给所有订阅了这个遗嘱主题的其它设备

    如果遗嘱标志被设置为1,连接标志中的遗嘱消息质量等级Will QoS和遗嘱是否保持字段Will Retain字段会被服务端用到,同时有 效载荷中必须包含遗嘱主题Will Topic和遗嘱消息Will Message字段

    如果遗嘱标志被设置为0,连接标志中的Will QoS和Will Retain字段必须设置为0,并且有效载 荷中不能包含Will Topic和Will Message字段

    遗嘱QoS Will QoS

    位置:连接标志的第4和第3位。

    遗嘱保留 Will Retain

    位置:连接标志的第5位。

    用户名标志 User Name Flag

    位置:连接标志的第7位。

    如果用户名(User Name)标志被设置为1,有效载荷中必须包含用户名字段

    密码标志 Password Flag

    位置:连接标志的第6位。 

    如果密码(Password)标志被设置为1,有效载荷中必须包含密码字段

    保持连接 Keep Alive (两个字节)

    他表示客户端必须在规定的时长之内向服务端发送消息保证客户端是存活状态,如果服务端认为客户端不是存活状态的话,那么他会断开客户端的网络连接

    CONNECT 报文的可变报头的示例

     有效载荷 Payload

     CONNECT报文的有效载荷(payload)包含一个或多个以长度为前缀的字段也就是一个或多个字符串,可变报头中的 标志决定是否包含这些字段。如果包含的话,必须按这个顺序出现:客户端标识符,遗嘱主 题,遗嘱消息,用户名,密码

    客户端标识符 Client Identifier

    服务端使用客户端标识符 (ClientId) 识别客户端。

    客户端标识符 (ClientId) 必须存在而且必须是CONNECT报文有效载荷的第一个字段

    遗嘱主题 Will Topic

     如果遗嘱标志被设置为1,有效载荷的下一个字段是遗嘱主题(Will Topic)。遗嘱主题必须是 1.5.3节定义的UTF-8编码字符串

    遗嘱消息 Will Message

    如果遗嘱标志被设置为1,有效载荷的下一个字段是遗嘱消息。

    用户名 User Name

    如果用户名(User Name)标志被设置为1,有效载荷的下一个字段就是它(用户名字符串)。用户名必须是 1.5.3节定义的UTF-8编码字符串 [MQTT-3.1.3-11]。服务端可以将它用于身份验证和授权。

    密码 Password

    如果密码(Password)标志被设置为1,有效载荷的下一个字段就是它(密码字符串)

    到这里MQTT控制报文的有效载荷部分结束了。

    当我们确定完MQTT---connect控制报文的可变报头部分和有效载荷部分之后,我们要根据可变报头的长度加上有效载荷的长度来赋值固定报头中的剩余长度,剩余长度字段等到最后再赋值

    CONNACK – 确认连接请求

    当服务器接收到客户端发来的请求连接时,服务端会向客户端响应确认请求连接报文,服务端发送CONNACK报文响应从客户端收到的CONNECT报文,服务端发送给客户端的第 一个报文必须是CONNACK。

    固定报头

    它的固定报头的第一个字节的高四位必须是数值2来表示当前的报文类型,低四位是保留位0,剩余长度是固定数值2

    可变报头 (两个字节)

    连接确认标志 Connect Acknowledge Flags

    第1个字节是 连接确认标志,位7-1是保留位且必须设置为0。 第0 (SP)位 是当前会话 (Session Present)标志。

     当前会话 Session Present

    位置:连接确认标志的第0位。

    如果服务端收到清理会话(CleanSession)标志为1的连接,除了将CONNACK报文中的返回 码设置为0之外,还必须将CONNACK报文中的当前会话设置(Session Present)标志为0 [MQTT-3.2.2-1]。

    如果服务端收到一个CleanSession为0的连接也就是不清除会话,当前会话标志的值取决于服务端是否已经保存了Client--Id对应客户端的会话状态。

    也就是说服务端会根据是否找到对应的客户端id的会话,来将0位是置零还是置一,找到了置一没找到清零

     连接返回码 Connect Return code

    位置:可变报头的第2个字节。

    用来表示客户端向服务端发起的连接,服务端是否接受,如果不接受,拒绝的原因是什么。如果服务端接受连接的话,它是返回0x00表示服务端已接受连接

     有效载荷

    CONNACK报文没有有效载荷。

    PUBLISH – 发布消息

    当我们的设备也就是客户端成功的与服务器建立了MQTT连接之后,他们就可以通过publish发布消息控制报文来进行通信

    PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。

    固定报头

    固定报头的第一个字节的高四位必须是数值3

     重发标志 DUP

    位置:第1个字节,第3位

    如果DUP标志被设置为0,表示这是客户端或服务端第一次请求发送这个PUBLISH报文。如 果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。对于QoS 0的消息,DUP标志必须设置为0 

    服务质量等级 QoS

    位置:第1个字节,第2-1位。

    这个字段表示应用消息分发的服务质量等级是多少,需不需要接受方发送应答。

     保留标志 RETAIN

    位置:第1个字节,第0位。

     

     如果客户端发给服务端的PUBLISH报文的保留(RETAIN)标志被设置为1,服务端必须存储 这个应用消息和它的服务质量等级(QoS),以便它可以被分发给未来的主题名匹配的订阅者。

    可变报头

    主题名 Topic Name

    主题名必须是PUBLISH报文可变报头的第一个字段。主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。

    PUBLISH报文中的主题名不能包含通配符-----详见MQTT协议手册4.7.1

    报文标识符 Packet Identifier

    只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文 中。

     假设主题名是a/b,报文标志符是10,那么publish报文可变报头就是‘a’‘/’‘b’这样的一个字符串加上前缀后面跟上报文标志符

    有效载荷 

    有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。可以发送以下两种

    响应

     动作 Actions

     客户端使用PUBLISH报文发送应用消息给服务端,目的是分发到其它订阅匹配的客户端。 服务端使用PUBLISH报文发送应用消息给每一个订阅匹配的客户端。

    PUBACK –发布确认

    当发送方使用publish报文发送了一个QoS等于1的消息,那么接收方必须使用发布确认报文来向发送方应答

    固定报头

    固定报头的第一个字节的高四位必须是数值4,来表示这个报文是发送确认报文,低四位是保留位,剩余长度是固定数值2 

    可变报头

    包含等待确认的PUBLISH报文的报文标识符。

     有效载荷

    PUBACK报文没有有效载荷。

    关于QoS等于2的相关控制报文呢在这里先不讲

    SUBSCRIBE - 订阅主题

    客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。

    固定报头

    固定报头的第一个字节的高四位必须是数值8,低四位是保留位0010

    剩余长度字段等于可变报头的长度(2字节)加上有效载荷的长度。 

    可变报头 

    可变报头包含报文标识符。

    有效载荷 

    SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。

    每一个过滤器后面跟着一个字节,这个字节被叫做 服务质量要求(Requested QoS)。它给 出了服务端向客户端发送应用消息所允许的最大QoS等级

    SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合

     响应

    服务端收到客户端发送的一个SUBSCRIBE报文时,必须使用SUBACK报文响应 [MQTT3.8.4-1]。SUBACK报文必须和等待确认的SUBSCRIBE报文有相同的报文标识符 

    SUBACK – 订阅确认

    当服务端接收到客户端给他发送的订阅主题报文时,服务端会向客户端返回订阅确认报文,服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。

    固定报头

    固定报头第一个字节的高四位数值是9,低四位是保留位0

    剩余长度字段 等于可变报头的长度加上有效载荷的长度。

    可变报头 

    可变报头包含等待确认的SUBSCRIBE报文的报文标识符。

    有效载荷 

    有效载荷包含一个返回码清单。每个返回码对应等待确认的SUBSCRIBE报文中的一个主题过 滤器。返回码的顺序必须和SUBSCRIBE报文中主题过滤器的顺序相同

    UNSUBSCRIBE –取消订阅 

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

    固定报头

    可变报头 

     可变报头包含一个报文标识符

    有效载荷 

    UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。 UNSUBSCRIBE报文中的主题过滤器必须是连续打包的

    UNSUBACK – 取消订阅确认

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

    固定报头

    可变报头 

    可变报头包含等待确认的UNSUBSCRIBE报文的报文标识符。

    有效载荷 

    UNSUBACK报文没有有效载荷。

    PINGREQ – 心跳请求

    我们的设备在连接MQTT服务端的时候,就设定了一个参数-----保持连接时长,服务端在一点五倍的保持连接时间内没有收到客户端的控制报 文,它必须断开客户端的网络连接,认为网络连接已断开

    为了保持设备与服务端的连接,我们需要定时向服务端发送心跳请求报文,这个定时时长尽量不要大于我们保持连接的时长

    固定报头

     剩余长度是0,因为他既没有可变报头也没有有效载荷

    PINGRESP – 心跳响应

    当服务端接收到客户端发送的心跳请求报文时,服务端向客户端响应--心跳响应报文,表示服务端还活着

    固定报头

    DISCONNECT –断开连接 

    我们的设备可以主动地向服务端发送断开连接报文,来主动向服务端断开连接,DISCONNECT报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接。

     响应

    客户端发送DISCONNECT报文之后:

    必须关闭网络连接,不能通过那个网络连接再发送任何控制报文

    服务端在收到DISCONNECT报文时:

    必须丢弃任何与当前连接关联的未发布的遗嘱消息,如果可客户端没有断开网络连接的话,服务端将会断开网络连接

  • 相关阅读:
    m基于GA遗传优化的GRNN广义回归神经网络销售数据预测算法matlab仿真
    android嵌入式开发及实训答案,android面试简历模板
    【第三方登录】微信web扫一扫登录步骤
    区块链审计 如何测试solidity的bool值占用几个字节
    Angr-CTF学习笔记11-13
    Nginx+Tomcat 搭建负载均衡、动静分离
    云服务器登录方式
    【Python】Python图形化界面库PySimpleGUI的简单使用
    在win10命令行(cmd)中添加临时环境变量
    mybatis开启缓存cache
  • 原文地址:https://blog.csdn.net/Paradise_Violet/article/details/125981730