MQTT协议原理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

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

与HTTP 协议一样,MQTT 协议也是应用层协议,工作在 TCP/IP 四层模型中的最上层(应用层),构建于 TCP/IP
协议上

MQTT协议主要特点:
1、使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。
2、消息传输不需要知道负载内容。
3、 支持 QoS 服务质量等级。
根据消息的重要性不同设置不同的服务质量等级
4、小型传输,开销很小,协议交换最小化,最大限度减少网络流量。
5、异常连接断开发生时,能通知到相关各方(遗嘱机制)。
6、支持心跳机制。

目前 MQTT 主流版本有两个,分别是 MQTT3.1.1 和 MQTT5。


一、基本概念

服务端:MQTT服务端通常是一台服务器(broker),它是MQTT信息传输的枢纽,负责将 MQTT客户端发送来的信息传递给 MQTT客户端;MQTT服务端还负责管理MQTT客户端,以确保客户端之间的通讯顺畅,保证 MQTT 信息得以正确接收和准确投递。

客户端:MQTT客户端可以向服务端发布信息,也可以从服务端收取信息;我们把客户端发送信息的行为称为发布信息。而客户端要想从服务端收取信息,则首先要向服务端订阅信息

MQTT 主题:客户端发布消息时需要为消息指定一个“主题”,表示将消息发布到该主题;而对于订阅消息的客户端来说,可通过订阅“主题”来订阅消息,这样当其它客户端或自己(当前客户端)向该主题发布消息时,MQTT 服务端就会将该主题的信息发送给该主题的订阅者(客户端)。

MQTT 发布/订阅特性客户端相互独立、空间上可分离、时间上可异步

QoS(服务质量):MQTT 协议有三种服务质量等级,QoS = 0(最多发一次),QoS = 1(最少发一次);QoS = 2(保证收一次)。无论是发布(PUBLISH)还是订阅(SUBSCRIBE),都可以使用数据包中的 qos 参数设置服务质量级别。

  • QoS 为 0 级时(最多发一次),MQTT 协议并不保证所有信息都能得以传输,MQTT 服务端和客户端不会对消息传输是否成功进行确认和检查,消息能否成功传输全看网络环境是否稳定。(发送一次之后就不管了,不管发送是否失败。)在网络环境稳定的情况下,信息传输一般是不会出现问题的。这完全依赖于 TCP 重传机制,如果网络不好,TCP 的重传也不是 100%可靠。
  • QoS 为 1 级时(至少发一次),发送端向接收端发送 PUBLISH 报文,当接收端收到 PUBLISH 报文后会向发送端回复一个 PUBACK 报文,如果发送端收到 PUBACK 报文,那么它就知道消息已经被接收端成功接收!假如过了一段时间后,发送端没有收到 PUBACK 报文,那么发送端会再次发送消息(发送 PUBLISH报文),然后再次等待接收端的 PUBACK 确认报文。当发送端重复发送一条消息时,会将 PUBLISH 报文中的 dup 标志设置为 true。
  • QoS为 2 级时(保证收一次),MQTT 协议可以确保接收端只接收一次消息(注意是只接收到一次,在 QoS=1 的情况下,接收端接收到消息的次数可能不止一次:>=1)。
    ① 首先发送端向接收端发送 PUBLISH 报文;
    ② 接收端接收到 PUBLISH 报文后,向发送端回复一个 PUBREC 报文(官方称其为–发布收到);
    ③ 发送端接收到 PUBREC 报文后,会再次向接收端发送 PUBREL 报文(官方称其为–发布释放);
    ④ 接收端接收到 PUBREL 报文后,会再次向发送端回复一个 PUBCOMP 报文(官方称其为–发布完成),如果发送端接收到 PUBCOMP 报文表示消息传输成功,它确认接收端已经成功接收到消息,整个过程结束!

若客户端在发布消息和订阅主题时使用不同级别的 QoS,将会发生什么情况呢?服务端会使用较低级别 QoS 来提供服务。

retain(保留标志)PUBLISH 报文中有一个 retain 标志,也就是保留标志,当 retain 设置为true 时表示保留消息,如果设置为 false 表示不保留消息。客户端向主题发布消息时将 retain 标志设置为true,以告诉服务端接收到此消息之后需要保留这个消息,这样服务端就会将该消息进行存储、保留。如果有其它客户端订阅了该消息对应的主题时,订阅之后都会马上收到该主题中的“保留消息”。

心跳机制:对于 MQTT 服务器来说,它要判断 MQTT 客户端是否依然与它保持着连接,就是检查该客户端是不是经常给它发送数据包,如果经常收到客户端的消息,那么证明该客户端肯定在线。无消息发送的空闲时段,可以采用心跳机制判断客户端是否在线。心跳机制的原理就在于:让客户端在没有向服务端发送消息的这个空闲时间里,定时向服务端发送一个心跳包,这个心跳包被称为心跳请求,其实质就是向服务端发送一个 PINGREQ 报文;当服务端收到PINGREQ 报文后就知道该客户端依然在线,然后向客户端回复一个 PINGRESP 报文,称为心跳响应!(通过 keepAlive 设置时间间隔)

遗嘱机制:MQTT 从诞生之初就是专为低带宽、高延迟或不可靠网络等环境而设计的;所以针对意外掉线的情况,MQTT 协议使用了遗嘱机制来服务客户端、管理客户端。客户端只有在意外掉线时才会发布遗嘱。
客户端连接服务端时发送的 CONNECT 报文中可以设置遗嘱消息

  • willTopic – 遗嘱主题:willTopic 的作用正是告知服务端,本客户端的遗嘱主题是什么。只有那些订阅了这一遗嘱主题的客户端才会收到本客户端的遗嘱消息。
  • willMessage – 遗嘱消息
  • willRetain – 遗嘱消息的保留标志
  • willQoS – 遗嘱消息的 QoS

MQTT的用户名和密码:同样可以在CONNECT报文中设置

二、MQTT控制报文组成

MQTT 控制报文由三部分组成:Fixed Header 固定报头(所有报文都有),Variable Header 可变报头(部分报文有),Payload 有效载荷(部分报文有)。

  1. 固定报头的格式
    固定报头的格式
  • MQTT控制报文的类型(byte1:bit7~4)
    “RESERVED”(保留), “CONNECT”(客户端请求连接服务端), “CONNACK”(连接报文确认), “PUBLISH”(发布消息), “PUBACK”(QoS 1 消息发布收到确认), “PUBREC”(QoS 2 消息发布收到), “PUBREL”(QoS 2 消息发布释放),“PUBCOMP”(QoS 2 消息发布完成), “SUBSCRIBE”(客户端订阅请求), “SUBACK”(订阅报文确认), “UNSUBSCRIBE”(客户端取消订阅请求), “UNSUBACK”(取消订阅报文确认),“PINGREQ”(心跳请求), “PINGRESP”(心跳响应), “DISCONNECT”(断开连接通知),“AUTH”(认证信息交换)。

    以上控制报文类型的值为0~15(从左至右,从上至下)

  • MQTT控制报文的标志(byte1:bit3~0)
    每个 MQTT 控制报文类型特定的标志如下表所示。表格中任何标记为“保留”的标志位,都是保留给以后使用的,必须设置为表格中列出的值。如果收到非法的标志,此报文被当做无效报文。
    MQTT控制报文的标志
    PUBLISH报文中的标志位含义:

  • DUP = PUBLISH 报文的重复分发标志

  • QoS = PUBLISH 报文的服务质量等级

  • RETAIN = PUBLISH 报文的保留标志

  • 剩余长度(byte2)
    用来表示当前控制报文剩余部分的字节数,包括可变报头和负载的数据。MQTT 控制报文总长度等于固定报头的长度加上剩余长度。

  1. 可变报头的格式
    可变报头部分在固定报头和有效载荷之间,可变报头的内容根据报文类型的不同而不同。
  • 报文标识符:部分类型 MQTT 控制报文的可变报头部分包含了2个字节的报文标识符字段。
    报文标识符
    (1)客户端每次发送一个新的 SUBSCRIBE,UNSUBSCRIBE 或者 PUBLISH(当 QoS>0 时)MQTT 控制报文时都必须分配一个当前未使用的非零报文标识符;服务端每次发送一个新的 PUBLISH(当 QoS>0)MQTT 控制报文时都必须分配一个当前未使用的非零报文标识符。
    (2)当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。某个报文标识符在某一时刻不能被多个命令所使用。
    (3)PUBACK,PUBREC 和 PUBREL 报文必须包含与最初发送的 PUBLISH 报文相同的报文标识符。类似地,SUBACK 和 UNSUBACK 必须包含在对应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使用的报文标识符。
    (4)在一次会话中对于客户端和服务端来说分属于不同的组。客户端和服务端彼此独立地分配报文标识符。客户端发送标识符为0x1234的 PUBLISH 报文,它有可能会在收到那个报文的PUBACK之前,先收到服务端发送的另一个不同的但是报文标识符也为0x1234的 PUBLISH 报文。

  • 属性:CONNECT,CONNACK,PUBLISH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBACK,DISCONNECT 和 AUTH 报文可变报头的最后一部分是一组属性。CONNECT报文的遗嘱(Will)属性字段中也包含了一组可选的属性。
    (1)属性字段由属性长度和所有属性组成。
    (2)属性长度被编码为变长字节整数。如果没有任何属性,必须由属性长度为零的字段来指示。
    (3)一个属性包含一段数据和一个定义了属性用途和数据类型的标识符。标识符被编码为变长字节整数。任何控制报文,如果包含了:对于该报文类型无效的标识符,或者错误类型的数据,都是无效报文。收到无效报文时,服务端或客户端使用包含原因码 0x81(无效报文)CONNACK 或 DISCONNECT 报文进行错误处理。
    (4)尽管属性标识符用变长字节整数来表示,但在此版本协议中,所有的标识符均由一个字节来表示。

  1. 有效载荷
    某些 MQTT 控制报文在报文的最后部分包含一个有效载荷
    在这里插入图片描述

三、部分MQTT控制报文格式

1、CONNECT – 连接请求
以一段CONNECT报文代码为例

uint16_t mqtt_connect_message(uint8_t *mqtt_message, char *client_id, char *username, char *password)
{
    uint16_t client_id_length = strlen(client_id);
    uint16_t username_length = strlen(username);
    uint16_t password_length = strlen(password);
    uint16_t packetLen;
    uint16_t i,baseIndex;
    
    packetLen = 12 + 2 + client_id_length;
    if(username_length > 0)
        packetLen = packetLen + 2 + username_length;
    if(password_length > 0)
        packetLen = packetLen+ 2 + password_length;
    
    mqtt_message[0] = 16;               //0x10 // MQTT Message Type CONNECT(固定报头)
    mqtt_message[1] = packetLen - 2;    //剩余长度(固定报头)
    baseIndex = 2;
    if(packetLen > 127)
    {
        mqtt_message[2] = 1;            //packetLen/127;    
        baseIndex = 3;
    }
    mqtt_message[baseIndex++] = 0;      // Protocol Name Length MSB(可变报头开始)
    mqtt_message[baseIndex++] = 4;      // Protocol Name Length LSB
    mqtt_message[baseIndex++] = 77;     // ASCII Code for M    
    mqtt_message[baseIndex++] = 81;     // ASCII Code for Q    
    mqtt_message[baseIndex++] = 84;     // ASCII Code for T    
    mqtt_message[baseIndex++] = 84;     // ASCII Code for T    
    mqtt_message[baseIndex++] = 4;      // MQTT Protocol version = 4
    mqtt_message[baseIndex++] = 2;      // Connect Flags()
    mqtt_message[baseIndex++] = 0;      // Keep-alive Time Length MSB
	mqtt_message[baseIndex++] = 60;     // Keep-alive Time Length LSB(可变报头结束)

	//(没有属性设置)
   
    //(有效载荷开始)
    mqtt_message[baseIndex++] = (0xff00&client_id_length)>>8;   // Client ID length MSB    
    mqtt_message[baseIndex++] = 0xff&client_id_length;          // Client ID length LSB    
    
    // Client ID
    for(i = 0; i < client_id_length; i++)
    {
        mqtt_message[baseIndex + i] = client_id[i];
    }
    baseIndex = baseIndex+client_id_length;
    
    if(username_length > 0)
    {
        //username    
        mqtt_message[baseIndex++] = (0xff00&username_length)>>8;//username length MSB    
        mqtt_message[baseIndex++] = 0xff&username_length;       //username length LSB    
        for(i = 0; i < username_length ; i++)
        {
            mqtt_message[baseIndex + i] = username[i];    
        }
        baseIndex = baseIndex + username_length;
    }
            
    if(password_length > 0)
    {
        //password    
        mqtt_message[baseIndex++] = (0xff00&password_length)>>8;//password length MSB    
        mqtt_message[baseIndex++] = 0xff&password_length;       //password length LSB    
        for(i = 0; i < password_length ; i++)
        {
            mqtt_message[baseIndex + i] = password[i];
        }
        baseIndex += password_length; 
	}
	//(有效载荷结束)

    return baseIndex;
}
  • 固定报头
    CONNECT固定报头

    剩余长度字段
    剩余长度等于可变报头的长度加上有效载荷的长度。编码方式为变长字节整数。

  • 可变报头
    CONNECT 报文的可变报头按下列次序包含四个字段:协议名(Protocol Name){协议名长度(高低字节),以及“M”“Q”“T”“T”},协议级别(Protocol Level){4代表使用MQTTv3.1.1,5代表使用MQTTv5.0},连接标志(Connect Flags){连接标志见下表},保持连接(Keep Alive)和属性(Properties)。

    连接标志字节:
    连接标志
    上述代码的连接标志只将Clean Start设置为1,如果需要使用用户名和密码登录,可以将bit7-6设置为1。Bit5:遗嘱保留标志,bit4-3:遗嘱服务质量,bit2:遗嘱标志。

  • 有效载荷
    根据可变报头中的连接标志,CONNECT载荷必须按照客户标识符(Client Identifier)、遗嘱属性(Will Properties)、遗嘱主题(Will Topic)、遗嘱载荷(Will Payload)、用户名(User Name)、密码(Password)的顺序出现。

载荷会先给出每个部分的长度(高低字节),再给出具体的内容,如:

mqtt_message[baseIndex++] = (0xff00&username_length)>>8;//username length MSB    
        mqtt_message[baseIndex++] = 0xff&username_length;       //username length LSB    
        for(i = 0; i < username_length ; i++)
        {
            mqtt_message[baseIndex + i] = username[i];    
        }

如果服务端拒绝了某个客户标识符(ClientID),它可以发送包含原因码 0x85(客户标识符无效)的CONNACK 报文作为对客户端的 CONNECT 报文的回应,之后必须关闭网络连接。

  1. CONNACK – 确认连接请求
    CONNACK 报文由服务端所发送,作为对来自客户端的 CONNECT 报文的响应。服务端在发送任何除AUTH以外的报文之前必须先发送包含原因码为 0x00(成功)的 CONNACK 报文。服务端在一次网络连接中不能发送多个 CONNACK 报文。

    如果客户端在合理的时间内没有收到服务端的 CONNACK 报文,客户端应该关闭网络连接。

  • 固定报头:略
  • 可变报头:连接确认标志(Connect Acknowledge Flags),连接原因码(Reason Code),属性(Properties)
    (1)连接确认标志,位 7-1 是保留位且必须设置为 0,第 0(SP)位是会话存在标志(Session Present Flag)。会话存在(Session Present)标志通知客户端,服务端是否正在使用此客户标识符之前连接的会话状态(Session State)。
    (2)如果服务端接受一个Clean Start为 1 的连接,服务端会把会话存在标志设置为 0;如果服务端接受一个Clean Start为 0 的连接,并且服务端已经保存了此客户标识符(ClientID)的会话状态(Session State),服务端在 CONNACK 报文中必须把会话存在标志设置为 1。
    (3)如果客户端没有保存的会话状态,但收到会话存在标志为 1,客户端必须关闭网络连接;如果客户端保存了会话状态,但收到的会话存在标志为 0,客户端若要继续此网络连接,它必须丢弃其保存的会话状态。
    (4)如果服务端收到一个格式正确的 CONNECT 报文,但服务端无法完成连接的创建,服务端可以发送一个包含适当的连接原因码的 CONNACK 报文。如果服务端发送了一个包含原因码大于等于 128 的 CONNACK 报文,它随后必须关闭网络连接。
    • 原因码:
    • 0 0x00 成功 连接被接受
    • 128 0x80 未指明的错误 服务端不愿透露的错误,或者没有适用的原因码
  • 属性:略
  • 有效载荷:CONNACK无需设置
  1. PUBLISH – 发布消息
uint16_t mqtt_publish_message(uint8_t *mqtt_message, char * topic, char * message, uint8_t qos)
{  
    uint16_t topic_length = strlen(topic);    
    uint16_t message_length = strlen(message);  
    uint16_t i,index=0;
    static uint16_t id=0;
    
    mqtt_message[index++] = 48 | (qos << 1;     //0x30 // MQTT Message Type PUBLISH    
    if(qos)
        mqtt_message[index++] = 2 + topic_length + 2 + message_length;
    else
   	 mqtt_message[index++] = 2 + topic_length + message_length;   // Remaining length   
 
    mqtt_message[index++] = (0xff00&topic_length)>>8;
    mqtt_message[index++] = 0xff&topic_length;
        
    // Topic    
    for(i = 0; i < topic_length; i++)
    {
        mqtt_message[index + i] = topic[i];
    }
    index += topic_length;
    
    if(qos)
    {
        mqtt_message[index++] = (0xff00&id)>>8;
        mqtt_message[index++] = 0xff&id;
        id++;
    }
        
    // Message
    for(i = 0; i < message_length; i++)
    {
        mqtt_message[index + i] = message[i];
    }
    index += message_length;
    
    return index;
}

  • 固定报头
    PUBLISH固定报头

  • 可变报头按顺序包含:主题名(Topic Name),报文标识符(Packet Identifier),属性(Properties)。
    备注:只有当 QoS 等级是 1 或 2 时,报文标识符(Packet Identifier)字段才能出现在 PUBLISH 报文中。

  • 有效载荷:包含将被发布的应用消息

  1. PUBACK – 发布确认
    PUBACK 报文是对 QoS 1 等级的 PUBLISH 报文的响应。
uint8_t mqtt_puback_message(uint8_t *mqtt_message)
{
    static uint16_t id=0;
    
    mqtt_message[0] = 64;               //0x40 //消息类型和标志 PUBACK
    mqtt_message[1] = 2;                //剩余长度(不包括固定头部)
    mqtt_message[2] = (0xff00&id)>>8;   //消息标识符
    mqtt_message[3] = 0xff&id;          //消息标识符
    id++;
    
    return 4;
}

  • 固定报头:略

  • 可变报头:所确认的PUBLISH报文标识符[通过mqtt_message[2], mqtt_message[3]设置],PUBACK 原因码[剩余长度为 2,则表示使用原因码 0x00(成功0)],属性长度[未设置],属性(Properties)[未设置]。
    备注:服务端或客户端发送 PUBACK 报文时必须设置其中一种 PUBACK 原因码。当原因码为0x00(成功)且没有属性时,原因码和属性长度可以被省略。在这种情况下,PUBACK 剩余长度为 2。

  • PUBACK 报文没有有效载荷。

  1. PUBREC – 发布已接收(QoS 2,第一步)
    PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。它是 QoS 2 等级协议交换的第二个报文。
    报文格式同"4. PUBACK – 发布确认"。

  2. PUBREL – 发布释放(QoS 2,第二步)
    PUBREL 报文是对 PUBREC 报文的响应。它是 QoS 2 等级协议交换的第三个报文。

  • 固定报头:按照规定格式设置。其中,PUBREL 固定报头的第 3,2,1,0 位是保留位,必须被设置为 0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接。
  • 可变报头:同上
  • 有效载荷:同上
  1. PUBCOMP – 发布完成(QoS 2,第三步)
    与上相同

  2. SUBSCRIBE - 订阅请求
    客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。每个订阅(Subscription)注册客户端所感兴趣的一个或多个主题。服务端向客户端发送 PUBLISH 报文以转发被发布到符合这些订阅主题的应用消息。SUBSCRIBE 报文同样(为每个订阅)指定了服务端可以向其发送的应用消息最大 QoS 等级。

  • 固定报头:按照规定格式设置,其中,SUBSCRIBE 报文固定报头的bit3-0是保留位,必须被设置为 0,0,1,0。服务端必须将其他的任何值都当做是不合法的并关闭网络连接。
  • 可变报头:报文标识符(Packet Identifier),属性(Properties)
  • 有效载荷:载荷必须包含至少一个主题过滤器/订阅选项对
    订阅选项的第 0 和 1 比特代表最大服务质量字段。最大服务质量字段为 3 将造成协议错误(Protocol Error);
    订阅选项的第 2 比特表示非本地(No Local)选项。值为 1,表示应用消息不能被转发给发布此消息的客户标识符。共享订阅时把非本地选项设为 1 将造成协议错误(Protocol Error);
    订阅选项的第 3 比特表示发布保留(Retain As Published)选项。值为 1,表示向此订阅转发应用消息时保持消息被发布时设置的保留(RETAIN)标志。值为 0,表示向此订阅转发应用消息时把保留标志设置为。当订阅建立之后,发送保留消息时保留标志设置为 1;
    订阅选项的第 4 和 5 比特表示保留操作(Retain Handling)选项。此选项指示当订阅建立时,是否发送保留消息。此选项不影响之后的任何保留消息的发送。如果没有匹配主题过滤器的保留消息,则此选项所有值的行为都一样。值可以设置为:
    0 = 订阅建立时发送保留消息
    1 = 订阅建立时,若该订阅当前不存在则发送保留消息
    2 = 订阅建立时不要发送保留消息
    保留操作的值设置为 3 将造成协议错误;
    订阅选项的第 6 和 7 比特为将来所保留。服务端必须把此保留位非 0 的 SUBSCRIBE 报文当做无效报文
    SUBSCRIBE报文载荷格式
    RAP 指发布保留(Retain as Published)。
    NL 指非本地(No Local)。

    格式示例:

SUBSCRIBE报文载荷格式示例

  1. SUBACK – 订阅确认
    服务端发送 SUBACK 报文给客户端,用于确认它已收到并且正在处理 SUBSCRIBE 报文。
  • 固定报头:略
  • 可变报头:所确认的 SUBSCRIBE 报文标识符,属性(Properties)。
  • 有效载荷:有效载荷包含一个原因码列表。每个原因码对应 SUBSCRIBE 报文中的一个被确认的主题过滤器。
    SUBACK原因码列表
    服务端发送 SUBACK 报文时必须对收到的每一个主题过滤器设置一种原因码
  1. UNSUBSCRIBE – 取消订阅请求
    客户端发送 UNSUBSCRIBE 报文给服务端,用于取消订阅主题
  • 固定报头:UNSUBSCRIBE 固定报头的第 3,2,1,0 位是保留位且必须分别设置为 0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接。
  • 可变报头:报文标识符和属性(Properties)。
  • 有效载荷:UNSUBSCRIBE 报文有效载荷必须包含至少一个主题过滤器。不包含有效载荷的UNSUBSCRIBE 报文将造成协议错误(Protocol Error)。
    相比较SUBSCRIBE没有订阅选项对
  1. UNSUBACK – 取消订阅确认
    服务端发送 UNSUBACK 报文给客户端用于确认收到 UNSUBSCRIBE 报文。
  • 固定报头:略

  • 可变报头:所确认的 UNSUBSCRIBE报文标识符,属性(Properties)。

  • 有效载荷:有效载荷包含一个原因码列表。每个原因码对应 UNSUBSCRIBE报文中的一个被确认的主题过滤器。

    备注:
    (1)UNSUBACK 报文中的原因码顺序必须与 UNSUBSCRIBE 报文中的主题过滤器顺序相匹配。
    (2)服务端发送 UNSUBACK 报文时对于每个收到的主题过滤器,必须使用一个取消订阅原因码。
    取消订阅原因码

  1. PINGREQ – PING 请求
    客户端发送 PINGREQ 报文给服务端,可被用于:
    a) 在没有任何其他 MQTT 控制报文从客户端发给服务端时,告知服务端客户端还活着。
    b) 请求服务端发送响应以确认服务端还活着。
    c) 使用网络已确认网络连接没有断开。
    此报文被用在保持连接(Keep Alive)的处理中。
  • 固定报头:按规定设置
  • 可变报头:无
  • 有效载荷:无
  1. PINGRESP – PING 响应
    服务端发送 PINGRESP 报文响应客户端的 PINGREQ 报文。表示服务端还活着。
    此报文被用在保持连接(Keep Alive)的处理中。
  • 固定报头:按规定设置
  • 可变报头:无
  • 有效载荷:无
  1. DISCONNECT – 断开通知
    DISCONNECT 报文是客户端发给服务端的最后一个 MQTT 控制报文。表示客户端为什么断开网络连接的原因。客户端和服务端在关闭网络连接之前可以发送一个 DISCONNECT 报文。如果在客户端没有首先发送包含原因码为 0x00(正常断开)DISCONNECT 报文并且连接包含遗嘱消息的情况下,遗嘱消息会被发布。
    服务端不能发送 DISCONNECT 报文,直到它发送了包含原因码小于 0x80 的 CONNACK 报文之后。
  • 固定报头:服务端或客户端必须验证所有的保留位都被设置为 0,如果他们不为 0,发送包含原因码为 0x81(无效报文)的 DISCONNECT 报文。

  • 可变报头:断开原因码,属性(Properties)
    断开原因码:

    0x00正常断开
    0x04包含遗嘱消息的断开
    其他略…

    客户端或服务端发送 DISCONNECT 报文时必须使用一种 DISCONNECT 原因码。如果原因码为 0x00(正常断开)且没有属性,原因码和属性长度可以被省略。这种情况下 DISCONNECT 报文剩余长度为 0。

声明

本文仅供个人学习使用,如有侵权,请联系删除。另外,如有错误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值