一、MQTT初探1、什么是MQTT?MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输协议),是一种发布/订阅(Publish/Subscribe)协议,是一种基于TCP/IP协议的轻量级通信协议。IBM于1999年发布,最新版本为v3.1.1。MQTT的优势在于可以用很少的代码和有限的带宽为远程设备提供实时可靠的消息服务。MQTT作为一种低开销、低带宽的即时通讯协议,在物联网、小型设备和移动应用中有着广泛的应用。当然,在物联网的发展中,MQTT并不是唯一的选择。与MQTT竞争的协议包括XMPP和CoAP协议。文末会有对比说明。2、MQTT是哪一层协议?众所周知,TCP/IP参考模型可以分为四层:应用层、传输层、网络层和链路层。TCP和UDP位于传输层,应用层常见的协议有HTTP、FTP、SSH等。MQTT协议运行在TCP之上,属于应用层协议,所以只要支持TCP/IP协议栈,就可以使用MQTT。3.MQTT消息格式每条MQTT命令消息的消息头都包含一个固定的头,部分消息携带可变头和载荷。消息格式如下:FixedHeader|可变标题|有效载荷和QoS级别以及其他标志位。第二个字节以剩余长度字段开始,它是后面的可变头加上消息负载的总长度,这个字段最多允许四个字节。剩余长度字段中单个字节的最大值二进制为0b01111111,十六进制为0x7F。也就是说,单个字节所能描述的最大长度是127字节。为什么不是256字节?因为MQTT协议规定,如果单个字节的第8位(***位)为1,则表示后面还有字节,第8位作为“继续位”。例如,数字64,编码为一个字节,十进制为64,十六进制为0×40。数字321(65+2*128)编码为两个字节,最重要的放在前面,第一个字节为65+128=193(0xC1),第二个字节为2(0x02),表示2×128.由于MQTT协议只允许最多4个字节来表示剩余长度(如表1所示),而最后一个字节的值只能是0x7F而不能是0xFF,所以可以发送的最大消息长度为256MB,而不是512MB。表15.变量头(VariableHeader)变量头主要包括协议名、协议版本、连接标志(ConnectFlags)、心跳间隔(KeepAlivetimer)、连接返回码(ConnectReturnCode)、主题名(TopicName)等,后面会针对主要部分进行说明。6.有效载荷(Payload)Payload直译为有效负载,可能会造成混淆,但实际上可以理解为消息体。当MQTT发送的消息类型为CONNECT(连接)、PUBLISH(发布)、SUBSCRIBE(订阅)、SUBACK(订阅确认)、UNSUBSCRIBE(取消订阅)时,会承载负载。二、MQTT的主要特点1、MQTT消息类型(MessageType)固定消息头的第一个字节包含连接标志(ConnectFlags),用于区分MQTT的消息类型。MQTT协议有14种不同的消息类型(如表2所示),可以简单分为连接和终止、发布和订阅、QoS2消息机制、各种确认ACK。至于每种消息类型会携带什么,这里就不细说了。表22.消息质量(QoS)MQTT消息质量分为三个级别,QoS0、QoS1和QoS2。QoS0:最多分发一次。消息的传输完全依赖于底层的TCP/IP网络。协议中没有定义响应和重试。消息要么只到达服务器一次,要么根本不到达服务器。QoS1:至少传送一次。服务器收到的消息由PUBACK消息确认。如果通信链路或发送设备出现异常,或在规定时间内未收到确认消息,则发送方将重新发送消息,并在消息头中设置DUP位。QoS2:只分发一次。这是最高级别的消息传递,消息丢失和重复是不可接受的,使用这种服务质量级别会有额外的开销。通过以下示例可以更深入地理解以上三个传输质量等级。比如目前流行的共享单车智能锁,智能锁可以定时使用QoS0级质量报文请求服务器发送自行车的当前位置。服务器收不到也不要紧,反正过段时间又要发了。之后,用户可以通过App查询周边自行车的位置。找到自行车后,需要解锁。这时可以使用QoS1级质量消息。手机App会不断的向自行车锁发送开锁信息,保证信息一次可达即可开锁。***用户用完单车后,需要提交支付单,可以使用QoSlevel2质量报文保证数据只发送一次,否则用户多付。3.WillFlag变量头的ConnectFlags字段(ConnectFlags)中有3个Will标志位:WillFlag、WillQoS和WillRetainFlag。这些Will字段用于监视客户端和服务器之间的连接状态。如果设置了WillFlag,则必须设置WillQoS和WillRetain标志位,并且WillTopic和WillMessage字段也必须包含在消息正文中。遗嘱信息呢?服务端与客户端通信时,出现异常或客户端心跳超时时,MQTT服务端会向客户端发出Will消息。当然,如果服务端收到客户端的DISCONNECT消息,是不会触发Will消息的发送的。因此,Will字段可以应用于设备下线后需要通知用户的场景。4.连接保活心跳机制(KeepAliveTimer)MQTT客户端可以设置一个心跳间隔(KeepAliveTimer),即在每个心跳间隔内发送一条消息。如果在这段时间内没有业务数据相关的消息,客户端会发送一个PINGREQ消息,相应的,服务器会返回一个PINGRESP消息进行确认。如果服务器在一个半(1.5)心跳间隔内没有收到客户端的消息,它将与客户端断开连接。心跳间隔的最大值可以设置为18小时左右,值为0表示客户端没有断开。5、MQTT的其他特性(1)异步发布/订阅实现了发布/订阅模式,解耦了发布消息的客户端(publisher)和订阅消息的客户端(subscriber)之间的关系,也就是说发布者和订阅者之间不需要直接连接。这种模式有以下优点:发布者和订阅者只需要知道同一个消息代理;发布者和订阅者不需要直接交互;发布者和订阅者不需要同时在线。由于发布/订阅实现,MQTT可以双向通信。也就是说,MQTT支持服务端对设备进行反向控制。设备可以订阅某个主题,然后发布者发布关于该主题的消息。设备收到消息后,可以进行一系列的操作。(2)二进制格式实现MQTT是基于二进制实现的,而不是基于字符串的,比如HTTP和XMPP都是基于字符串实现的。由于HTTP和XMPP的协议头很长,而MQTT的固定头只有两个字节,发送一条消息相比其他协议最节省流量。下一页《工业物联网核心技术——MQTT(二)》
