zoukankan      html  css  js  c++  java
  • MQTT协议(二)——控制报文之连接服务端报文(CONNECT)与确认连接请求(CONNACK)

    一、CONNECT – 连接服务端

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

    在一个网络连接上,客户端只能发送一次CONNECT报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接 。

    有效载荷包含一个或多个编码的字段。包括客户端的唯一标识符,Will主题,Will消息,用户名和密码。

    除了客户端标识之外,其它的字段都是可选的,基于标志位来决定可变报头中是否需要包含这些字段。

    1.固定头

    固定头没啥可说的的,报文类型是1.

    2.可变头

    可变头一个完整报文如下:

    --1~6个字节为协议名

    MQTT协议名是预先规定好的,这个后续不会变。

    --第7个字节为协议级别

    其实就是mqtt协议的修订版本。对于3.1.1版协议,协议级别字段的值是4(0x04)。

    如果发现不支持的协议级别,服务端必须给发送一个返回码为0x01(不支持的协议级别)的CONNACK报文响应CONNECT报文,然后断开客户端的连接。

    --第8个字节为连接标志

    连接标志字节包含一些用于指定MQTT连接行为的参数。它还指出有效载荷中的字段是否存在。有效荷载里有啥全看这个字节的8位字符是0还是1了。

      |--第0位:服务端必须验证CONNECT控制报文的保留标志位(第0位)是否为0,如果不为0必须断开客户端连接。

      |--第1位:清理会话 Clean Session

          这个二进制位指定了会话状态的处理方式。客户端和服务端可以保存会话状态,以支持跨网络连接的可靠消息传输。这个标志位用于控制会话状态的生存时间。

            这个值是0:服务端可以根据报文里的客户端标识符,来找之前这个客户端有没有连过,连过的话就恢复之前的会话状态,没有的话就新建一个会话。

            就算是这个连接断开了,会话也要保存在服务端,针对这个客户端订阅的消息,会保存为会话的一部分,在这个客户端重新连接后,把这些

            消息再推送给这个客户端。

            这个值是1:服务端丢弃之前所有的和这个客户端建立的会话,并开始一个新的会话,新的会话仅持续和网络连接同样长的时间。

            与这个会话关联的状态数据不能被任何之后的会话重用。

            为了确保在发生故障时状态的一致性,客户端应该使用会话状态标志1重复请求连接,直到连接成功。

            一般来说,客户端连接时总是将清理会话标志设置为0或1,并且不交替使用两种值。这个选择取决于具体的应用。

            清理会话标志设置为1的客户端不会收到旧的应用消息,而且在每次连接成功后都需要重新订阅任何相关的主题。清理会话标志设置为0的客户端会收到所有在它连接断开期间发布的QoS 1和QoS 2级别的消息。

               因此,要确保不丢失连接断开期间的消息,需要使用QoS 1或 QoS 2级别,同时将清理会话标志设置为0。

            清理会话标志0的客户端连接时,它请求服务端在连接断开后保留它的MQTT会话状态。如果打算在之后的某个时间点重连到这个服务端,客户端连接应该只使用清理会话标志0。

            当客户端决定之后不再使用这个会话时,应该将清理会话标志设置为1最后再连接一次,然后断开连接。

      |--第2位:遗嘱标志 Will Flag

          遗嘱比较有用,比如说你手机app订阅了你家扫地机器人的在线状态topic,这个在线状态扫地机器人可以通过遗嘱来实现,一旦它断开了与mqttbroker连接,mqttboker就可以发送机器人在连接时就设置好的遗嘱,通知手机机器人掉线了。

          遗嘱标志(Will Flag)被设置为1,表示如果连接请求被接受了,遗嘱(Will Message)消息必须被存储在服务端并且与这个网络连接关联。也就是确认使用遗嘱。

          之后网络连接关闭时,服务端必须发布这个遗嘱消息,除非服务端收到DISCONNECT报文时删除了这个遗嘱消息。

          如果决定启用遗嘱,那么连接标志中的Will QoS和Will Retain字段会被服务端用到,同时有效载荷中必须包含Will Topic和Will Message字段。因为你得组织服务端遗嘱的publish的报文。

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

      |--第3位、第4位:遗嘱QoS Will QoS

          没啥说的,遗嘱也是一个publish的消息,需要确定的消息等级。

      |--第5位:遗嘱保留 Will Retain

          如果遗嘱消息被发布时需要保留,需要指定这一位的值。     

    tips:
      保留消息是mqtt中比较重要的概念,它是统治服务器是否保留本条报文,以推送给后来订阅者的。比如描述设备状态的报文,这个就留在服务端就行,只要设备状态不改变,就没有必要修改这个报文,后续订阅设备状态的也能什么时候订阅什么时候收到,非常方便。

      |--第6位:用户名标志 User Name Flag

          这设置0,有效载荷就不能有了,设置1就必须有这个字段。

      |--第7位:密码标志 Password Flag

          同上

    --第9第10个字节:保持连接 Keep Alive

      保持连接(Keep Alive)是一个以秒为单位的时间间隔,表示为一个16位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。

      如果没有任何其它的控制报文可以发送,客户端必须发送一个。保持连接的实际值是由应用指定的,一般是几分钟。允许的最大值是18小时12分15秒。

    3.有效载荷

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

    有个概念必须要了解--客户端标识符 Client Identifier,也就是客户端的唯一标识。服务端使用客户端标识符 (ClientId) 识别客户端。连接服务端的每个客户端都有唯一的客户端标识符(ClientId)。客户端和服务端都必须使用ClientId识别两者之间的MQTT会话相关的状态。

    客户端标识符 (ClientId) 必须存在而且必须是CONNECT报文有效载荷的第一个字段 ,客户端标识符必须是1.5.3节定义的UTF-8编码字符串。

    二、CONNACK – 确认连接请求

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

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

    1.固定报文头

    固定头没啥可说的的,报文类型是2.

    2.可变报文头

     主要有两个字节:

    --第一个字节是连接确认标志,8位里面就第0位有用,其他都是0不用管。

    第0位标识的是当前会话,也就是服务端告诉客户端你在我这的session是我新启动的(值是0),还是原来就有的,我只是重用(值是1)

    如果之前客户端发的连接报文,让服务端清理clientsession,那服务端的session肯定是新建的,那这个标志就是0,或者是之前客户端就没连过,那这个值也是0 。

    如果连接报文没有让服务端清理clientsession,并且之前客户端连接过,服务器用的是原来的会话,那这个值就是1 。

    --第二个字节是连接返回码

    连接返回码字段使用一个字节的无符号值【见下表】。如果服务端收到一个合法的CONNECT报文,但出于某些原因无法处理它,服务端应该尝试发送一个包含非零返回码(表格中的某一个)的CONNACK报文。

    如果服务端发送了一个包含非零返回码的CONNACK报文,那么它必须关闭网络连接 。

     如果认为上表中的所有连接返回码都不太合适,那么服务端必须关闭网络连接,不需要发送CONNACK报文。

    3.有效荷载

    CONNACK报文没有有效载荷。

     三、断开连接

    DISCONNECT报文是客户端发给服务端的最后一个控制报文。表示客户端正常断开连接。服务端收到这个报文后,把这个客户端的遗言也要删除了。

    1.固定头

    控制报文类型是14,其他没啥。

    2.可变头

    没有可变头。

    3.有效载荷

    没有有效载荷。

  • 相关阅读:
    POJ 1811 Prime Test 素性测试 分解素因子
    sysbench的安装与使用
    电脑中已有VS2005和VS2010安装.NET3.5失败的解决方案
    I.MX6 show battery states in commandLine
    RPi 2B Raspbian system install
    I.MX6 bq27441 driver porting
    I.MX6 隐藏电池图标
    I.MX6 Power off register hacking
    I.MX6 Goodix GT9xx touchscreen driver porting
    busybox filesystem httpd php-5.5.31 sqlite3 webserver
  • 原文地址:https://www.cnblogs.com/pandaNHF/p/14103555.html
Copyright © 2011-2022 走看看