`
hongtoushizi
  • 浏览: 376949 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

MQTT协议笔记之连接和心跳

    博客分类:
  • mqtt
阅读更多

前言

本篇会把连接(CONNECT)、心跳(PINGREQ/PINGRESP)、确认(CONNACK)、断开连接(DISCONNECT)和在一起。

CONNECT

像前面所说,MQTT有关字符串部分采用的修改版的UTF-8编码,CONNECT可变头部中协议名称、消息体都是采用修改版的UTF-8编码。前面基本上可变头部内容不多,下面是一个较为完整的CONNECT消息结构:

  Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
    Message Type(1) DUP flag QoS level RETAIN
byte 1
  0 0 0 1 x x x x
byte 2 Remaining Length
Variable header/可变头部
Protocol Name
byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
byte 2 Length LSB (6) 0 0 0 0 0 1 1 0
byte 3 'M' 0 1 0 0 1 1 0 1
byte 4 'Q' 0 1 0 1 0 0 0 1
byte 5 'I' 0 1 0 0 1 0 0 1
byte 6 's' 0 1 1 1 0 0 1 1
byte 7 'd' 0 1 1 0 0 1 0 0
byte 8 'p' 0 1 1 1 0 0 0 0
Protocol Version Number
byte 9 Version (3) 0 0 0 0 0 0 1 1
Connect Flags
  User Name Flag Password Flag Will Retain Will QoS Will Flag Clean Session Reserved
byte 10
1 1 0 0 1 1 1 x
Keep Alive timer
byte 11 Keep Alive MSB (0) 0 0 0 0 0 0 0 0
byte 12 Keep Alive LSB (10) 0 0 0 0 1 0 1 0
Playload/消息体

Client Identifier(客户端ID)

1-23个字符长度,客户端到服务器的全局唯一标志,如果客户端ID超出23个字符长度,服务器需要返回码为2,标识符被拒绝响应的CONNACK消息。
处理QoS级别1和2的消息ID中,可以使用到。
必填项。

Will Topic

Will Flag值为1,这里便是Will Topic的内容。QoS级别通过Will QoS字段定义,RETAIN值通过Will RETAIN标识,都定义在可变头里面。

Will Message

Will Flag若设为1,这里便是Will Message定义消息的内容,对应的主题为Will Topic。如果客户端意外的断开触发服务器PUBLISH此消息。
长度有可能为0。
在CONNECT消息中的Will Message是UTF-8编码的,当被服务器发布时则作为二进制的消息体。

User Name

如果设置User Name标识,可以在此读取用户名称。一般可用于身份验证。协议建议用户名为不多于12个字符,不是必须。

Password

如果设置Password标识,便可读取用户密码。建议密码为12个字符或者更少,但不是必须。

可变头部

协议名称和协议版本都是固定的。

连接标志(Connect Flags)

一个字节表示,除了第1位是保留未使用,其它7位都具有不同含义。

业务上很重要,对消息总体流程影响很大,需要牢记。

Clean Session

0,表示如果订阅的客户机断线了,要保存为其要推送的消息(QoS为1和QoS为2),若其重新连接时,需将这些消息推送(若客户端长时间不连接,需要设置一个过期值)。 1,断线服务器即清理相关信息,重新连接上来之后,会再次订阅。

Will Flag

定义了客户端(没有主动发送DISCONNECT消息)出现网络异常导致连接中断的情况下,服务器需要做的一些措施。

简而言之,就是客户端预先定义好,在自己异常断开的情况下,所留下的最后遗愿(Last Will),也称之为遗嘱(Testament)。 这个遗嘱就是一个由客户端预先定义好的主题和对应消息,附加在CONNECT的可变头部中,在客户端连接出现异常的情况下,由服务器主动发布此消息。

只有在Will Flag位为1时,Will Qos和Will Retain才会被读取,此时消息体Playload中要出现Will Topic和Will Message具体内容,否则,Will QoS和Will Retain值会被忽略掉。

Will Qos

两位表示,和PUBLISH消息固定头部的QoS level含义一样。这里先掠过,到PUBLISH消息再回过头来看看,会更明白些。

若标识了Will Flag值为1,那么Will QoS就会生效,否则会被忽略掉。

Will RETAIN

如果设置Will Flag,Will Retain标志就是有效的,否则它将被忽略。

当客户端意外断开服务器发布其Will Message之后,服务器是否应该继续保存。这个属性和PUBLISH固定头部的RETAIN标志含义一样,这里先掠过。

User name 和 password Flag:

用于授权,两者要么为0要么为1,否则都是无效。都为0,表示客户端可自由连接/订阅,都为1,表示连接/订阅需要授权。

Playload/消息体

消息体定义的消息顺序(如上表所示),约定俗成,不得更改,否则将可能引起混乱。

若Will Flag值为0,那么在Playload中,Client Identifer后面就不会存在Will Topic和Will Message内容。

若User Name和Password都为0,意味着Playload/消息体中,找不到User Name和password的值,就算有,也是无效。标志决定着是否读取与否。

心跳时间(Keep Alive timer)

以秒为单位,定义服务器端从客户端接收消息的最大时间间隔。一般应用服务会在业务层次检测客户端网络是否连接,不是TCP/IP协议层面的心跳机制(比如开启SOCKET的SO_KEEPALIVE选项)。 一般来讲,在一个心跳间隔内,客户端发送一个PINGREQ消息到服务器,服务器返回PINGRESP消息,完成一次心跳交互,继而等待下一轮。若客户端没有收到心跳反馈,会关闭掉TCP/IP端口连接,离线。 16位两个字节,可看做一个无符号的short类型值。最大值,2^16-1 = 65535秒 = 18小时。最小值可以为0,表示客户端不断开。一般设为几分钟,比如微信心跳周期为300秒。

Will Message编码

Will Message在CONNECT Payload/息体中,使用UTF-8编码。假设内容为“abcd”,大概如下:

  Description 7 6 5 4 3 2 1 0
byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
byte 2 Length LSB (4) 0 0 0 0 0 1 0 0
byte 3 'a' (0x61) 0 1 1 0 0 0 0 1
byte 4 'b' (0x62) 0 1 1 0 0 0 1 0
byte 5 'c' (0x63) 0 1 1 0 0 0 1 1
byte 6 'd' (0x64) 0 1 1 0 0 1 0 0

有一点需要记住,PUBLISH的Payload/消息体中以二进制编码保存。

某刻客户端异常关闭触发服务器会PUBLISH此消息。那么服务器会直接把byte3-byte6之间字符取出,保存为二进制,附加到PUBLISH消息体中,大概存储如下:

  Description 7 6 5 4 3 2 1 0
byte 1 'a' (0x61) 0 1 1 0 0 0 0 1
byte 2 'b' (0x62) 0 1 1 0 0 0 1 0
byte 3 'c' (0x63) 0 1 1 0 0 0 1 1
byte 4 'd' (0x64) 0 1 1 0 0 1 0 0

另外,MQTT 3.1协议对Will message的说明很容易引起误解,3.1.1草案已经得到修正。

相关说明:

http://mqtt.org/wiki/doku.php/willmessageutf8_support

https://tools.oasis-open.org/issues/browse/MQTT-2

连接异常中断通知机制

CONNECT消息一旦设置在可变头部设置了Will flag标记,那就启用了Last-Will-And-Testament特性,此特性很赞。

一旦客户端出现异常中断,便会触发服务器发布Will Message消息到Will Topic主题上去,通知Will Topic订阅者,对方因异常退出。

接收CONNECT后的响应动作

接收到CONNECT消息之后,服务器应该返回一个CONNACK消息作为响应:

  1. 若客户端绕过CONNECT消息直接发送其它类型消息,服务器应关闭此非法连接 若客户端发送CONNECT之后未收到CONNACT,需要关闭当前连接,然后重新连接
  2. 相同Client ID客户端已连接到服务器,先前客户端必须断开连接后,服务器才能完成新的客户端CONNECT连接 客户端发送无效非法CONNECT消息,服务器需要关闭

CONNACK

一个完整的CONNACK消息大致如下:

  Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1   Message type (2) DUP flag QoS flags RETAIN
    0 0 1 0 x x x x
byte 2   Remaining Length (2)
    0 0 0 0 0 0 1 0
Variable header/可变头部
Topic Name Compression Response
byte 1 Reserved values. Not used. x x x x x x x x
Connect Return Code
byte 2 Return Code                

可变头部第一个字节为保留,无甚用处。第二个字节为连接握手返回码:

返回值 16进制 含义
0 0x00 Connection Accepted
1 0x01 Connection Refused: unacceptable protocol version
2 0x02 Connection Refused: identifier rejected
3 0x03 Connection Refused: server unavailable
4 0x04 Connection Refused: bad user name or password
5 0x05 Connection Refused: not authorized
6-255   Reserved for future use

只有0-5目前被使用到,其他值有待日后使用。一般返回值为0x00,表示连接建立。非法的请求,需要返回相应的数值。

从上面看出,一个CONNACT,四个字节表示。一个正常的CONNACT消息实际内容可能如下: 0x20 0x02 0x00 0x00

若是在私有协议中,两个字节就足够了。

很多时候,客户端和服务器端在没有消息传递时,会一直保持着连接。虽然不能依靠TCP心跳机制(比如SO_KEEPALIVE选项),业务层面定义心跳机制,会让连接状态检测、控制更为直观。

PINGREQ

由客户端发送到服务器端,证明自己还在一直连接着呢。两个字节,固定值。

  Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1   Message type (12) DUP flag QoS flags RETAIN
    1 1 0 0 x x x x
byte 2   Remaining Length (0)
    0 0 0 0 0 0 0 0

客户端会在一个心跳周期内发送一条PINGREQ消息到服务器端。

心跳频率在CONNECT可变头部“Keep Alive timer”中定义时间,单位为秒,无符号16位short表示。

PINGRESP

服务器收到PINGREQ请求之后,会立即响应一个两个字节固定格式的PINGRESP消息。

  Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1   Message type (13) DUP flag QoS flags RETAIN
    1 1 0 1 x x x x
byte 2   Remaining Length (0)
    0 0 0 0 0 0 0 0

服务器一般若在1.5倍的心跳周期内接收不到客户端发送的PINGREQ,可考虑关闭客户端的连接描述符。此时的关闭连接的行为和接收到客户端发送DISCONNECT消息的处理行为一致,但对客户端的订阅不会产生影响(不会清除客户端订阅数据),这个需要牢记。

若客户端发送PINGREQ之后的一个心跳周期内接收不到PINGRESP消息,可考虑关闭TCP/IP套接字连接。

DISCONNECT

客户端主动发送到服务器端,表明即将关闭TCP/IP连接。此时要求服务器要完整、干净的进行断开处理,不能仅仅类似于关闭连接描述符类似草草处理之。 需要两个字节,值固定:

  Description 7 6 5 4 3 2 1 0
Fixed header/固定头部
byte 1   Message type (14) DUP flag QoS flags RETAIN
    1 1 1 0 x x x x
byte 2   Remaining Length (0)
    0 0 0 0 0 0 0 0

服务器要根据先前此客户端在发送CONNECT消息可变头部Connect flag中的“Clean session flag”所设置值,再次复习一下:

  1. 值为0,服务器必须在客户端断开之后继续存储/保持客户端的订阅状态。这些状态包括:

    • 存储订阅的消息QoS1和QoS2消息
    • 正在发送消息期间连接丢失导致发送失败的消息
    • 以便当客户端重新连接时以上消息可以被重新传递。
  2. 值为1,服务器需要立刻清理连接状态数据。

有一点需要牢记,服务器在接收到客户端发送的DISCONNECT消息之后,需要主动关闭TCP/IP连接。

 

转载自: http://www.blogjava.net/yongboy/archive/2014/02/09/409630.html

分享到:
评论

相关推荐

    MQTT协议笔记-打印版

    MQTT协议笔记-打印版, 来自:聂永的博客 熟读此笔记, 基本上对MQTT协议会很熟悉! 7. MQTT 3.1.1,值得...2. MQTT协议笔记之连接和心跳 nieyong 2014-02-09 13:41 1. MQTT协议笔记之头部信息 nieyong 2014-02-07 17:35

    MQTT 协议 5.0 中文版

    MQTT 协议 5.0 的技术委员会成员包括 Brian Raymor(Microsoft)、Richard Coppen(IBM)、Andrew Banks(IBM)、Ed Briggs(Microsoft)、Ken Borgendale(IBM)和 Rahul Gupta(IBM)。 MQTT 协议 5.0 的相关文档...

    C语言实现的MQTT协议连接阿里云

    使用自己用C语言实现的MQTT协议来连接阿里云平台。 并利用多线程相关知识,创建一个线程专门接收来自阿里云平台的数据。 在demo中,给出了 CONNECT连接 PUBLISH发布消息 SUBSCRIBE订阅 UNSUBSCRIBE取消订阅 PING保活...

    C语言版本MQTT协议,连接阿里云物联网平台客户端代码

    总的来说,利用C语言实现MQTT客户端连接阿里云物联网平台,需要深入理解MQTT协议,熟悉C语言编程,并能够正确使用选择的MQTT库。同时,对阿里云物联网平台的API和规则要有清晰的认识,以便编写出可靠的物联网应用。

    ESP8266通过MQTT协议连接OneNet云.zip

    为了深入了解和实施此项目,你需要掌握STM32的嵌入式编程,了解基本的TCP/IP协议和MQTT协议,熟悉ESP8266的AT指令集,以及OneNet云平台的API和设备管理。压缩包中的资源将为你提供必要的代码和指导,但具体实现可能...

    MQTT协议完整中文版版.pdf

    MQTT协议的英文全称和缩写经常在文档、论坛和开发者交流中被提及,是物联网和移动设备通信中不可忽视的标准协议之一。 在MQTT协议的控制报文中,具体包含了如下报文类型及其作用: - CONNECT:客户端向服务器发起...

    C++实现mqtt协议

    总的来说,C++实现MQTT协议主要涉及理解MQTT协议的基本概念,选择合适的客户端库(如Eclipse Paho),以及正确地使用库提供的接口来建立连接、订阅和发布消息。通过这种方式,你可以构建出高效且可靠的物联网应用,...

    MQTT协议中文版.pdf

    MQTT协议广泛应用于机器与机器的通信(M2M)和物联网环境(IoT)。 MQTT协议的主要特点有: * 轻量级:MQTT协议的设计思想是轻巧的,易于实现和部署。 * 基于publish/subscribe模式:MQTT协议采用publish/...

    MQTT协议资料及源码

    MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息协议,主要用于物联网(IoT)领域,尤其适合资源有限的设备和低带宽、高延迟或不可靠的网络环境。这个压缩包文件包含了关于MQTT协议的相关...

    mqtt协议文档(中文版)

    **MQTT协议详解** MQTT(Message Queuing Telemetry ...总的来说,MQTT协议凭借其轻量、高效、可靠的特点,已经成为物联网领域中不可或缺的通信协议之一。随着物联网技术的发展,MQTT的应用场景也将不断拓展和深化。

    4G通过MQTT协议ONENET,mqtt通信协议,MDK

    在"4G通过MQTT协议ONENET"的项目中,你将学习到如何结合4G通信技术和MQTT协议,利用ONENET平台实现物联网设备的远程管理和数据交换。这个过程不仅涉及到网络编程,还涵盖了物联网设备的硬件接口、数据处理以及云平台...

    MQTT协议中文版 pdf 文档下载

    MQTT协议因其轻量级、高效的特性,成为物联网和M2M通信领域的首选协议之一。理解其核心概念、操作流程和安全措施,对于开发和维护与MQTT相关的应用程序至关重要。通过提供的中文文档,开发者可以更方便地学习和掌握...

    Android基于MQTT协议的长连接demo

    在这个“Android基于MQTT协议的长连接demo”中,我们将深入探讨如何在Android应用中集成和使用MQTT服务。 首先,我们需要一个MQTT服务提供商或自建MQTT服务器,如Mosquitto、HiveMQ等。服务器负责处理客户端的订阅...

    STM32+MQTT协议功能实现

    在本文中,我们将深入探讨如何在STM32 F103VE型号上实现MQTT协议功能,以及如何与迪发物联(DeveIoT)平台进行连接。 MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅模式的网络协议,特别...

    整理的MQTT协议

    MQTT协议支持心跳机制,客户端可以通过设置Keep Alive参数来维持连接。如果在Keep Alive时间内没有收发任何报文,服务器会认为客户端断开,并可能触发断线重连。 ### 5. 持久化订阅(Will Message) 客户端在连接...

    MQTT_协议_3.1.1_中文版.pdf

    - MQTT协议支持客户端和服务端架构,通过网络连接进行消息传输。 - 该协议被设计为轻巧、开放、简单、规范,易于实现,并且对资源限制的环境特别友好。 - 协议可以运行在TCP/IP上,或者其他提供有序、可靠、双向...

    基于STM32执行的MQTT协议 源程序与资料

    基于STM32执行的MQTT协议 源程序与资料 基于STM32执行的MQTT协议 源程序与资料 基于STM32执行的MQTT协议 源程序与资料 基于STM32执行的MQTT协议 源程序与资料 基于STM32执行的MQTT协议 源程序与资料 基于STM32执行的...

    MQTT中英文协议和协议注释.zip

    通过心跳报文`PINGREQ`和`PINGRESP`维持客户端和服务端的连接状态,防止因网络问题导致的连接超时。 7. **Last Will and Testament (LWT)** LWT允许客户端在连接断开时,预先设置一条遗嘱消息,当服务端检测到...

    MQTT 协议 3.1.1 中文版

    MQTT 协议 3.1.1 中文版 MQTT(Message Queuing Telemetry Transport)是一...MQTT 技术委员会是 OASIS 下面的一个技术委员会,负责制定和维护 MQTT 协议的标准。技术委员会成员包括来自 IBM、StormMQ 等公司的专家。

Global site tag (gtag.js) - Google Analytics