MQTT-新一代物联网协议

本文深入探讨MQTT协议,一种轻量级的物联网通信协议,用于机器间通信。介绍了MQTT的消息结构、固定头部、可变头部、消息体、连接标志和心跳机制。MQTT适用于低带宽、不可靠连接的场景,广泛应用于Android消息推送和物联网应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、MQTT - MQ Telemetry Transport

 
  • 轻量级的 machine-to-machine 通信协议。
  • publish/subscribe模式。
  • 基于TCP/IP。
  • 支持QoS。
  • 适合于低带宽、不可靠连接、嵌入式设备、CPU内存资源紧张。
  • 是一种比较不错的Android消息推送方案。
  • FacebookMessenger采用了MQTT。
  • MQTT有可能成为物联网的重要协议。
 

消息体

 
 
 

MessageType

 
 
 
CONNECT
TCP连接建立完毕后,Client向Server发出一个Request。
如果一段时间内接收不到Server的Response,则关闭socket,重新建立一个session连接。
如果一个ClientID已经与服务器连接,则持有同样ClientID的旧有连接必须由服务器关闭后,新建立才能建立。
 
CONNACK
Server发出Response响应。
0x00 Connection Accepted
0x01 Connection Refused: unacceptable protocol version
0x02 Connection Refused: identifier rejected
0x03 Connection Refused: server unavailable
0x04 Connection Refused: bad user name or password
0x05 Connection Refused: not authorized
 
PUBLISH 发布消息
Client/Servier均可以进行PUBLISH。
publish message 应该包含一个TopicName(Subject/Channel),即订阅关键词。
 
关于Topic通配符
/:用来表示层次,比如a/b,a/b/c。
#:表示匹配>=0个层次,比如a/#就匹配a/,a/b,a/b/c。
单独的一个#表示匹配所有。
不允许 a#和a/#/c。
+:表示匹配一个层次,例如a/+匹配a/b,a/c,不匹配a/b/c。
单独的一个+是允许的,a+不允许,a/+/b不允许
 
PUBACK 发布消息后的确认
QoS=1时,Server向Client发布该确认(Client收到确认后删除),订阅者向Server发布确认。
 
PUBREC / PUBREL / PUBCOMP
QoS=2时
1. Server->Client发布PUBREC(已收到);
2. Client->Server发布PUBREL(已释放);
3. Server->Client发布PUBCOMP(已完成),Client删除msg;
订阅者也会向Server发布类似过程确认。
 
PINGREQ / PINGRES 心跳
Client有责任发送KeepAliveTime时长告诉给Server。在一个时长内,发送PINGREQ,Server发送PINGRES确认。
Server在1.5个时长内未收到PINGREQ,就断开连接。
Client在1个时长内未收到PINGRES,断开连接。
一般来说,时长设置为几个分钟。最大18hours,0表示一直未断开。
 
 

QoS

 
 
QoS=0:最多一次,有可能重复或丢失。
 
QoS=1:至少一次,有可能重复。
Client[Qos=1,DUP=0/*重复次数*/,MessageId=x] --->PUBLISH--> Server收到后,存储Message,发布,删除,向Client回发PUBACK
Client收到PUBACK后,删除Message;如果未收到PUBACK,设置DUP++,重新发送,Server端重新发布,所以有可能重复发送消息。
 
QoS=2:只有一次,确保消息只到达一次(用于比较严格的计费系统)。
 
 

Clean Session

 
如果为false(flag=0),Client断开连接后,Server应该保存Client的订阅信息。
如果为true(flag=1),表示Server应该立刻丢弃任何会话状态信息。


二、协议初解

先说一下整个协议的构造,整体上协议可拆分为:

                    固定头部+可变头部+消息体

协议说白了就是对于双方通信的一个约定,比如传过来一段字符流,第1个字节表示什么,第2个字节表示什么。。。。一个约定。

所以在固定头部的构造如下:

1、MessageType(0和15保留,共占4位)

public $operations=array(
         "MQTT_CONNECT"=>1,//请求连接
         "MQTT_CONNACK"=>2,//请求应答
         "MQTT_PUBLISH"=>3,//发布消息
         "MQTT_PUBACK"=>4,//发布应答
         "MQTT_PUBREC"=>5,//发布已接收,保证传递1
         "MQTT_PUBREL"=>6,//发布释放,保证传递2
         "MQTT_PUBCOMP"=>7,//发布完成,保证传递3
         "MQTT_SUBSCRIBE"=>8,//订阅请求
         "MQTT_SUBACK"=>9,//订阅应答
         "MQTT_UNSUBSCRIBE"=>10,//取消订阅
         "MQTT_UNSUBACK"=>11,//取消订阅应答
         "MQTT_PINGREQ"=>12,//ping请求
         "MQTT_PINGRESP"=>13,//ping响应
         "MQTT_DISCONNECT"=>14//断开连接
        ); 

2、DUP flag

 其是用来在保证消息传输可靠的,如果设置为1,则在下面的变长头部里多加MessageId,并需要回复确认,保证消息传输完成,但不能用于检测消息重复发送。

3、Qos

主要用于PUBLISH(发布态)消息的,保证消息传递的次数。

00表示最多一次 即<=1

01表示至少一次  即>=1

10表示一次,即==1

11保留后用

4、Retain

 主要用于PUBLISH(发布态)的消息,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它。如果不设那么推送至当前订阅的就释放了。

5、固定头部的byte 2

是用来保存接下去的变长头部+消息体的总大小的。

但是不是并不是直接保存的,同样也是可以扩展的,其机制是,前7位用于保存长度,后一部用做标识。

我举个例了,即如果计算出后面的大小为0<length<=127的,正常保存

如果是127<length<16383的,则需要二个字节保存了,将第一个字节的最大的一位置1,表示未完。然后第二个字节继续存。

拿130来说,第一个字节存10000011,第二个字节存000000001,也就是0x83,0x01,把两个字节连起来看,第二个字节权重从2的8次开始。

同起可以加第3个字节,最多可以加至第4个字节。故MQTT协议最多可以实现268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)将近256M的数据。可谓能伸能缩。

 可变头部

这个是可变头部的全貌。

1、首先最上面的8个字节是Protocol Name(编码名),UTF编码的字符“MQIsdp”,头两个是编码名提长为6。

这里多说一些,接下去的协议多采用这种方式组合,即头两个字节表示下一部分的长,然后后面跟上内容。这里头两个字节长为6,下面跟6个字符“MQIsdp”。

2、Protocol Version,协议版本号,v3 也是固定的。

3、Connect Flag,连接标识,有点像固定头部的。8位分别代表不同的标志。第1个字节保留。

Clean Session,Will flag,Will Qos, Will Retain都是相对于CONNECT消息来说的。

Clean Session:0表示如果订阅的客户机断线了,那么要保存其要推送的消息,如果其重新连接时,则将这些消息推送。

                            1表示消除,表示客户机是第一次连接,消息所以以前的连接信息。

Will Flag表示如果客户机在不是在发送DISCONNECT消息中断,比如IO错误等,将些置为1,要求重传。并且下且的WillQos和WillRetain也要设置,消息体中的Topic和MessageID也要设置,就是表示发生了错误,要重传。

Will Qos,在CONNECT非正常情况下设置,一般如果标识了WillFlag,那么这个位置也要标识。

Will RETAIN:同样在CONNECT中,如果标识了WillFlag,那么些位也一定要标识

usename flag和passwordflag,用来标识是否在消息体中传递用户和密码,只有标识了,消息体中的用户名和密码才用效,只标记密码而不标记用户名是不合法的。

4、Keep Alive,表示响应时间,如果这个时间内,连接或发送操作未完成,则断开tcp连接,表示离线。

5、Connect Return Code即通常于CONNACK消息中,表示返回的连接情况,我可以通过此检验连接情况。

6、Topic Name,订阅消息标识,MQTT是基于订阅/发布的消息,那么这个就是消息订阅的标识,像新闻客户端里的订阅不同的栏目一样。用于区别消息的推送类别。

主要用于PUBLISH和SUBSCRIBE中。最大可支持32767个字符,即4个字节。

消息体(PayLoad)

只有3种消息有消息体CONNECT,SUBSCRIBE,SUBACK

CONNECT主要是客户机的ClientID,订阅的Topic和Message以及用户名和密码,其于变长头部中的will是对应的。

SUBSCRIBE是包含了一系列的要订阅的主题以及QOS。

SUBACK是用服务器对于SUBSCRIBE所申请的主题及QOS进行确认和回复。

PUBLISH是消息体中则保存推送的消息,以二进制形式,当然这里的编辑可自定义。

7、Message Identifier

包含于PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.

其为16位字符表示,用于在Qos为1或2时标识Message的,保证Message传输的可靠性。

至于具体的消息例子,我们在后面的代码中慢慢体现。


三、MQTT协议笔记之头部信息

前言

MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约、轻量,易于使用,针对受限环境(带宽低、网络延迟高、网络通信不稳定),可以简单概括为物联网打造,官方总结特点如下:

1.使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
2. 对负载内容屏蔽的消息传输。
3. 使用 TCP/IP 提供网络连接。
4. 有三种消息发布服务质量:
    “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
    “至少一次”,确保消息到达,但消息重复可能会发生。
    “只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
5. 小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量。
6. 使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。

MQTT 3.1协议在线版本: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html

官方下载地址: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/MQTT_V3.1_Protocol_Specific.pdf

PDF版本,42页,不算多。

另外,目前MQTT大家都用在了手机推送,可能还有很多的使用方式,有待进一步的探索。

协议方面,以前曾简单实现过一点HTTP协议,基于HTTP上构建若干种通信管道的socket.io协议,不过socket.io 0.9版本的协议才两三页而已。面对领域不同,自然解决的方式也不一样。

阅读完毕MQTT协议,有一个想法,其实可以基于MQTT协议,打造更加私有、精简(协议一些地方,略显多余)的传输协议,比如一个字节的传输开销。有时间,会详细说一下。

固定头部

固定头部,使用两个字节,共16位:

bit 7 6 5 4 3 2 1 0
byte 1 Message Type DUP flag QoS level RETAIN
byte 2 Remaining Length

第一个字节(byte 1)

消息类型(4-7),使用4位二进制表示,可代表16种消息类型:

Mnemonic Enumeration Description
Reserved 0 Reserved
CONNECT 1 Client request to connect to Server
CONNACK 2 Connect Acknowledgment
PUBLISH 3 Publish message
PUBACK 4 Publish Acknowledgment
PUBREC 5 Publish Received (assured delivery part 1)
PUBREL 6 Publish Release (assured delivery part 2)
PUBCOMP 7 Publish Complete (assured delivery part 3)
SUBSCRIBE 8 Client Subscribe request
SUBACK 9 Subscribe Acknowledgment
UNSUBSCRIBE 10 Client Unsubscribe request
UNSUBACK
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值