• 转载MQTT


    转载地址:https://www.cnblogs.com/wdg-blog/p/12532836.html

    1. 概述

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布,目前最新版本为v3.1.1。MQTT最大的优点在于可以以极少的代码和有限的带宽,为远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,MQTT在物联网、小型设备、移动应用等方面有广泛的应用。众所周知,TCP/IP参考模型可以分为四层:应用层、传输层、网络层、链路层。TCP和UDP位于传输层,应用层常见的协议有HTTP、FTP、SSH等。MQTT协议运行于TCP之上,属于应用层协议,因此只要是支持TCP/IP协议栈的地方,都可以使用MQTT。

    2. MQTT客户端

    一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的网络连接。客户端可以:
    (1)发布其他客户端可能会订阅的信息;  //发布消息
    (2)订阅其它客户端发布的消息;   //订阅消息
    (3)退订或删除应用程序的消息;    //退订消息
    (4)断开与服务器连接。        //断开,连接服务器

    3. MQTT服务器

    MQTT服务器以称为“消息代理”(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:
    (1)接受来自客户的网络连接;         //接受客户端连接
    (2)接受客户发布的应用信息;        //接收客户端发布的消息
    (3)处理来自客户端的订阅和退订请求;    //处理消息的订阅及退订
    (4)向订阅的客户转发应用程序消息。     //推送消息

    4. MQTT消息格式

    每条MQTT命令消息的消息头都包含一个固定的报头,有些消息会携带一个可变报文头和一个负荷。消息格式如下:

    固定报文头 | 可变报文头 | 负荷

    4.1 固定报文头(Fixed Header)

    MQTT固定报文头最少有两个字节,第一字节包含消息类型(Message Type)和QoS级别等标志位。第二字节开始是剩余长度字段,该长度是后面的可变报文头加消息负载的总长度,不包括用于编码剩余长度字段本身的字节数,该字段最多允许四个字节。

    图4-1固定报头报文结构


    剩余长度字段单个字节最大值为二进制0b0111 1111,16进制0x7F。也就是说,单个字节可以描述的最大长度是127字节。为什么不是256字节呢?因为MQTT协议规定,单个字节第八位(最高位)若为1,则表示后续还有字节存在,第八位起“延续位”的作用。
    例如,数字64,编码为一个字节,十进制表示为64,十六进制表示为0×40。数字321(65+2*128)编码为两个字节,重要性最低的放在前面,第一个字节为65+128=193(0xC1),第二个字节是2(0x02),表示2×128。
    由于MQTT协议最多只允许使用四个字节表示剩余长度(如表1),并且最后一字节最大值只能是0x7F不能是0xFF,所以能发送的最大消息长度是256MB,而不是512MB。

    图4-2数据包类型


    图4-3数据包类型标识位

    4.2 可变报文头(Variable Header)

    可变报文头主要包含协议名、协议版本、连接标志(Connect Flags)、心跳间隔时间(Keep Alive timer)、连接返回码(Connect Return Code)、主题名(Topic Name)等,后面会针对主要部分进行讲解。

    图4-4可变报头结构

    4.2.1 消息质量(QoS)

    MQTT消息质量有三个等级,QoS 0,QoS 1和 QoS 2。
    QoS 0:最多分发一次。消息的传递完全依赖底层的TCP/IP网络,协议里没有定义应答和重试,消息要么只会到达服务端一次,要么根本没有到达。
    QoS 1:至少分发一次。服务器的消息接收由PUBACK消息进行确认,如果通信链路或发送设备异常,或者指定时间内没有收到确认消息,发送端会重发这条在消息头中设置了DUP位的消息。
    QoS 2:只分发一次。这是最高级别的消息传递,消息丢失和重复都是不可接受的,使用这个服务质量等级会有额外的开销。

    4.2.2 遗愿标志(Will Flag)

    在可变报文头的连接标志位字段(Connect Flags)里有三个Will标志位:Will Flag、Will QoS和Will Retain Flag,这些Will字段用于监控客户端与服务器之间的连接状况。如果设置了Will Flag,就必须设置Will QoS和Will Retain标志位,消息主体中也必须有Will Topic和Will Message字段。
    那遗愿消息是怎么回事呢?服务器与客户端通信时,当遇到异常或客户端心跳超时的情况,MQTT服务器会替客户端发布一个Will消息。当然如果服务器收到来自客户端的DISCONNECT消息,则不会触发Will消息的发送。
    因此,Will字段可以应用于设备掉线后需要通知用户的场景。

    4.2.3 连接保活心跳机制(Keep Alive Timer)

    MQTT客户端可以设置一个心跳间隔时间(Keep Alive Timer),表示在每个心跳间隔时间内发送一条消息。如果在这个时间周期内,没有业务数据相关的消息,客户端会发一个PINGREQ消息,相应的,服务器会返回一个PINGRESP消息进行确认。如果服务器在一个半(1.5)心跳间隔时间周期内没有收到来自客户端的消息,就会断开与客户端的连接。心跳间隔时间最大值大约可以设置为18个小时,0值意味着客户端不断开

    4.3 有效负荷(Payload)

    Payload直译为负荷,可能让人摸不着头脑,实际上可以理解为消息主体(body)。

    图4-5消息结构


    当MQTT发送的消息类型是CONNECT(连接)、PUBLISH(发布)、SUBSCRIBE(订阅)、SUBACK(订阅确认)、UNSUBSCRIBE(取消订阅)时,则会带有负荷。
    (1)CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。
    (2)SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS。
    (3)SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
    (4)UNSUBSCRIBE,消息体内容是要订阅的主题。
    (5)PUBLISH,消息体内容是相关主题的数据。

    5. MQTT控制报文

    介绍MQTT协议的报文组成并通过wireshark抓取报文包分析报文内容

    5.1 连接服务端(CONNECT)

    Connect报文在MQTT客户端连接服务器时发出,报文由三部分组成,下面将分别介绍

    5.1.1 固定报头(fixed header)

    图5-1 CONNECT固定报头报文


    Connect名称的值为1,低四位保留,剩余长度保存可变报头(10字节)加上有效载荷的长度。

    5.1.2 可变报头(variable header)

    Connect报文的可变报头包含协议名,协议等级,连接标志和保持连接

    图5-2 CONNECT可变报头报文


    报文协议名之前有两个字节的报文标识符,唯一标识这条报文。

    连接标志包含用户名标志(username flag)、密码标志(password flag)、遗嘱标志(will flag)、遗嘱服务指令(will Qos)、遗嘱保留标志(will retain)、清除会话标志(clean session)、保留位(reserved)。
    用户名标志(username flag):若用户名标志被置为1,有效载荷中必须包含用户名字段。
    密码标志(password flag):若密码标志被置为1,有效载荷中必须包含密码字段,当用户标志被置为0时,密码标志必须被置0.。
    遗嘱标志(will flag):若遗嘱标志被置1,遗嘱服务指令(will Qos)与遗嘱保留标志(will retain)会被服务器用到,遗嘱消息中必须包含will topic和will message。
    遗嘱服务指令(will Qos):如果遗嘱标志被设置为0,遗嘱QoS也必须设置为0(0x00),如果遗嘱标志被设置为1,遗嘱QoS的值可以等于0(0x00),1(0x01),2(0x02)。它的值不能等 于3。
    遗嘱保留标志(will retain):若遗嘱保留标志位被置位,服务器将保留遗嘱消息(保留发布),当客户端异常断开连接时将遗嘱发给订阅遗嘱主题的客户。
    清除会话标志(clean session):标志被设置为1,客户端和服务端必须丢弃之前的任何会话并开始一个新的会话(之前的订阅与发布消息被删除),若标志为0,恢复与服务器会话连接,若没有连接 新建一个会话连接(不删除之前与客户端的会话信息并保存断开本次会话之后的Qos1与Qos2消息)。
    保留位(reserved):如果不为0必须断开客 户端连接。

    报文最后两字节为发送心跳包的间隔时间,当客户端没有数据发给服务器时,须发送心跳包(pingreq)到服务器,保证连接不断开。

    5.1.3 有效载荷(Payload)

    CONNECT报文的有效载荷(payload)包含一个或多个以长度为前缀的字段,可变报头中的 标志决定是否包含这些字段。如果包含的话,必须按这个顺序出现:客户端标识符,遗嘱主题,遗嘱消息,用户名,密码。
    客户端标识符(client identifier):服务器通过识别客户标识符,确定客户端,识别两者间的MQTT会话相关状态,服务器允许客户端提供一个零字节的标识符,但clean session必须置1。

    图5-3 CONNECT消息报文

    5.2连接请求确认(CONNACK)

    Connack为服务器确认客户端连上服务给出的回应。

    5.2.1 固定报头(fixed header)

    图5-4 CONNACK固定报头报文

    5.2.2 可变报头(variable header)

    图5-5 CONNACK可变报头报文

     

    • 第一字节1~7位保留,第0位是当前会话标志(session present),若清除会话标志被置1,该位为0,若清除会话标志为0且服务器没有与客户端会话保存,该位置0,有保存置1
      第二字节保存连接返回码,若连接成功返回0。



    图5-6 连接返回码



    图5-7 CONNECT响应报文

    5.3发布消息(PUBLISH)

    发布消息可由客户端或服务器发出,被消息订阅者接收。

    5.3.1 固定报头(fixed header)

    图5-8 PUBLISH固定报头报文


    固定报头第一字节的低四位分别保存重发标志(DUP),服务质量(Qos),保留标志(RETAIN)。
    重发标志(DUP):当该位被置1,表示该条报文为重发报文,客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1。对于QoS 0的消息,DUP标志必须设置为0。
    服务质量(Qos):表示发送质量,取值有00 01 10。
    保留标志(RETAIN):若该位被置1,表示服务器必须保存其应用消息和质量等级,若为0,表示该消息不须保存,如果服务端收到一条保留(RETAIN)标志为1的QoS 0消息,它必须丢弃之前为那个主题保留的任何消息。它应该将这个新的QoS0消息当作那个主题的新保留消息,但是任何时候都可以选择丢弃它,保留标志为1且有效载荷为零字节的PUBLISH报文会被服务端当作正常消息处理,它会被发送给订阅主题匹配的客户端。此外,同一个主题下任何现存的保留消息必须被移除,因此这个主题之后的任何订阅者都不会收到一个保留消息。

    5.3.2 可变报头(variable header)

    可变报头按顺序包含主题名和报文标识符。

    5.3.3 有效载荷(Payload)

    若Qos为0,无响应,若Qos为1,返回PUBACK报文,若Qos为2,返回PUBREC报文。

    图5-9 publish消息报文

    5.4发布确认(PUBACK)

    由服务器或客户端确认已接收到pub消息

    5.4.1 固定报头(fixed header)

    图5-10 puback固定报头报文

    5.4.2 可变报头(variable header)

    只有两字节的报文标识(报文标识为pub报文标识)

    图5-11 puback消息报文

    5.5发布收到 PUBREC(QoS 2,第一步)

    5.5.1 固定报头(fixed header)

    图5-12 pubrec固定报头报文

    5.5.2 可变报头(variable header)

    只有两字节的报文标识(报文标识为pub报文标识)

    图5-13 pubrec消息报文

    5.6发布释放 PUBREL(QoS 2,第二步)

    5.6.1 固定报头(fixed header)

    图5-14 pubrel固定报头报文

    5.6.2 可变报头(variable header)

    只有两字节的报文标识(报文标识为pub报文标识)

    图5-15 pubrel消息报文

    5.7发布完成 PUBCOMP(QoS 2,第三步)

    5.7.1 固定报头(fixed header)

    图5-16 pubcomp固定报头报文

    5.7.2 可变报头(variable header)

    只有两字节的报文标识(报文标识为pub报文标识)

    图5-17 pubcomp消息报文

    5.8订阅主题(SUBSCRIBE)

    客户端通过订阅消息的方式来接收服务端下发的消息

    5.8.1 固定报头(fixed header)

    SUBSCRIBE控制固定报头的第3,2,1,0位是保留位,必须分别设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接

    图5-18 subscribe固定报头报文

    5.8.2 可变报头(variable header)

    只有两字节的报文标识

    5.8.3 有效载荷(Payload)

    图5-19 subscribe有效载体报文


    消息载体包含若干主题过滤器和服务质量等级
    PUB时指定的qos是服务器肯定按此规则接收,但是最终订阅者不一定。
    SUB时指定的qos表示订阅者可以接收的最高消息等级,也就是可能收到更低等级的消息


    图5-20 subscribe消息报文

    5.9订阅确认(SUBACK)

    SUBACK报文包含一个返回码清单,它们指定了SUBSCRIBE请求的每个订阅被授予的最大QoS等级。

    5.9.1 固定报头(fixed header)

    图5-21 suback固定报头报文

    5.9.2 可变报头(variable header)

    只有两字节的报文标识

    5.9.3 有效载荷(Payload)

    图5-22 suback有效载体报文


    允许的返回码为0x00-最大Qos0,0x01-最大Qos1,0x02-最大Qos2,0x80-失败

    图5-23 suback消息报文

    5.10取消订阅 (UNSUBSCRIBE)

    5.10.1 固定报头(fixed header)

    图5-24 unsubscribe固定报头报文

    5.10.2 可变报头(variable header)

    只有两字节的报文标识

    5.10.3 有效载荷(Payload)

    包含需要取消订阅的主题过滤器的列表.

    图5-25 unsubscribe消息报文

    5.11取消订阅确认 (UNSUBACK)

    5.11.1 固定报头(fixed header)

    图5-26 unsuback固定报头报文

    5.11.2 可变报头(variable header)

    只有两字节的报文标识(报文标识为unsub报文标识)

    图5-27 unsuback消息报文

    5.12心跳请求 (PINGREQ)

    客户端发送PINGREQ报文给服务端的。用于:
    1.在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
    2.请求服务端发送 响应确认它还活着。
    3.使用网络以确认网络连接没有断开

    5.12.1 固定报头(fixed header)

    图5-28 pingreq固定报头报文



    图5-29 pingreq消息报文

    5.13心跳响应 (PINGRESP)

    5.13.1 固定报头(fixed header)

    图5-30 pingresp固定报头报文



    图5-31 pingresp消息报文

    5.14断开连接 (DISCONNECT)

    5.14.1 固定报头(fixed header)

    图5-32 disconnect固定报头报文



    图5-33 disconnect消息报文

    抓包注意:用标准不加密MQTT能抓到便于查看的报文,加密报文解析时不便于理解

    创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

    清风 | 文 【原创】

    如果本篇博客有任何错误,请批评指教,不胜感激 !

  • 相关阅读:
    jQuery下拉框级联实现
    js获取当前月的天数
    jQuery获取select选中值的文本
    JSTL常用代码总结
    matplotlib.basemap安装失败的解决
    获取MODIS MCD19A2气溶胶数据(AOD)并用GDAL转换投影坐标
    keras 显示错误 无法保存model图片_ImportError: Failed to import pydot.
    ArcGIS处理每个栅格图行列号一致且上下对齐
    北京DEM数据下载
    最新 夜光遥感影像VIIRS&DMSP下载总结
  • 原文地址:https://www.cnblogs.com/maanshancss/p/12534207.html
Copyright © 2020-2023  润新知