PS:鉴于本人最近再写毕设初稿,老师强调要写清楚MQTT协议,特留下本文,为正在或未来即将淋雨的兄弟们撑把伞,有不足或写错的问题或错误欢迎指正。
MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)和物联网网环境(IoT)。
MQTT最开始是为了卫星通讯而设计,所以其设计是专门针对低带宽、高延迟或不可靠的网络而设计的,这些特点是MQTT协议的核心特点。目前,MQTT协议已经从嵌入式系统应用拓展到开放的物联网(IoT)领域,有了更广阔的应用领域。
在网络通讯里,从电脑a到电脑b,我们一般会用http协议。MQTT是一种比http更简单的顶层协议,在MQTT组成的协议中,网络一般为中心分布型,所有设备节点既可能是发布者,也可能是订阅者,他们都会连在中心服务器上。
在MQTT协议中包括三个东西:发布者(Publisher),订阅者(Subscriber)和服务器(Broker)。这三者也可简单分为客户端和服务端。
客户端包括发布者和订阅者,它们一般都是手机,电脑或者其他物联网设备等终端。订阅者,终端发出信息,将消息发到服务器,服务器再将消息以订阅的方式转发给订阅者。
服务端,一般是云服务器。MQTT服务端通常是一台服务器。它是MQTT信息传输的枢纽,负责将MQTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。构成以服务器为中心的网络。这就是MQTT的通讯模型。下图所示为MQTT的通讯示意图。
所有网络协议的根本都是实现不同设备之间的点对点通信。http协议想实现点对点通信,如发布者想把消息发给订阅者,首先需要知道订阅者的IP,通过IP二者才能进行通讯。而MQTT协议是一种基于TCP/IP协议的一种应用层协议,通过主题(topic)实现二者的连接。主题就是字符串,发布者发布了一个字符串,而订阅者订阅了同名的字符串,这时二者间就形成了连接。通过这种方式,通信的双方不需要知道对方是谁就可以进行通讯,极大地简化了通讯的过程。
发布者将需要发送的内容放在消息中发出,消息中蕴含的内容叫负载(Payload),负载一般也是字符串,发布者将消息发布后,订阅者只需要订阅该主题就能获取消息。
MQTT协议的客户端和服务端在进行通讯前需要先进行连接。首先MQTT客户端将会向服务端发送连接请求。该请求实际上是一个包含有连接请求信息的数据包(也叫报文),这个数据包的官方名称为CONNECT。在MQTT服务端收到客户端连接请求后,会向客户端发送连接确认。同样的,该确认也是一个数据包,叫做CONNACK。
MQTT客户端要想连接服务端,首先要向服务端发送CONNECT报文。如果此CONNECT报文的格式或内容不符合MQTT规范,则服务器会拒绝客户端的连接请求。下图为CONNECT的内容格式。
在CONNECT数据包中,clientId存放的是该客户端的名字,同一个服务器不能连接重名的节点;cleanSession的意思是清除会话。在MQTT协议使用的过程中,服务器会保存一些重要的消息,此时cleanSession的值为flase,即保存数据,ture代表清除数据。keepAlive的意思是心跳时间间隔,代表间隔多久确认一次连接状态,上图的例子代表的是每隔60s确认一次。
上述的三个参数是CONNECT数据包必须包含的,其余的参数都是可以加入也可以去掉的。
当服务器收到连接请求后,会向客户端发CONNACK数据包作为回应。其具体结构如下图所示。
sessionPresent的意思是当前会话,如果服务器中有要发回客户端但是没有发出的消息时,sessionPresent就会置为ture。
returnCode在这里是连接返回码的意思,其中0代表连接成功,其余都是连接被服务器拒绝。1代表不支持客户端的MQTT协议版本;2为不支持客户端标识符的编码,可能是客户端标识符编码是UTF-8;3是服务端不可用;4为用户名或密码无效;5是客户端未被授权连接到此服务端。
当客户端和服务端的连接完成之后,就可以进行正常通讯了。首先由发布者发出消息,其结构如下:
packetId就是报文标识符,是MQTT自动添加的,方便MQTT对报文进行管理,一般很少用到;topicName就是主题名,是字符串。订阅者通过订阅这个字符串来接收相应的数据;retainFlag表示保持标志位,如果服务器接收到客户端的数据时,其值如果为ture,便会将数据保存;dupFlag表示重复标志位,当其为ture时,会将服务器存储的值重复发给客户端。payload作为负载内容,是消息中需要传达的内容。
QoS表示消息质量,MQTT消息质量有三个等级,QoS 0,QoS 1和 QoS 2。QoS 0最多分发一次。消息的传递完全依赖底层的TCP/IP网络,协议里没有定义应答和重试,消息要么只会到达服务端一次,要么根本没有到达。消息可能会丢失;QoS 1至少分发一次。服务器的消息接收由PUBACK消息进行确认,如果通信链路或发送设备异常,或者指定时间内没有收到确认消息,发送端会重发这条在消息头中设置了DUP位的消息。QoS 2只分发一次。这是最高级别的消息传递,消息丢失和重复都是不可接受的,使用这个服务质量等级会有额外的开销。
订阅者订阅主题也需要发送SUBSCRIBE报文,其包括订阅主题名,qos,报文标识符和返回码returnCode。其中主题名可以有多个,对应订阅者可以订阅多个主题。returnCode有四个值,0、1、2分别对应QoS的三个等级,还有128表示订阅失败。
同时订阅者也需要返回服务器一个返回数据包SUBACK,包括订阅返回码和报文标识符。
有订阅就有取消,取消报文包括报文标识符还要要取消订阅主题的名字。
通过上述所有内容,就可以实现MQTT协议。