深入理解mqtt协议,mqtt测试

MQTT协议

MQTT是轻量级基于代理的发布/订阅的消息传输协议,它可以通过很少的代码和带宽和远程设备连接。例如通过卫星和代理连接,通过拨号和医疗保健提供者连接,以及在一些自动化或小型设备上,而且由于小巧,省电,协议开销小和能高效的向一和多个接收者传递信息,故同样适用于称动应用设备上

 

Mqtt协议特点

1.使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。

2.协议简单,最小的头部只需2个字节,特别适合于嵌入式中。

3.对负载内容屏蔽的消息传输。

4.使用 TCP/IP 提供网络连接。

5.有三种消息发布服务质量:

(1) “至多一次,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。

(2) “至少一次,确保消息到达,但消息重复可能会发生。

(3) “只有一次,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

6. 使用 Last Will Testament 特性通知有关各方客户端异常中断的机制。

 

 

PUB/SUB 模型

 



 

Mqtt结构

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

bit

7

6

5

4

3

2

1

0

byte 1

Message Type

DUP flag

QoS level

RETAIN

byte 2

Remaining Length

 

消息类型

使用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

11

Unsubscribe Acknowledgment----接触订阅反馈

PINGREQ

12

PING Request-------心跳检测

PINGRESP

13

PING Response----心跳反馈

DISCONNECT

14

Client is Disconnecting----客户端断开连接

Reserved

15

Reserved----保留待用

 

 

消息类型使用的场景这里我使用的是wireshark 抓包工具

 

首先我先来测试demo1也就是消息类型QOS

 

 

 

代码中我没有设置QOS类型所以他会默认选0

 

至多发送一次,发送即丢弃。没有确认消息,也不知道对方是否收到

 



 

 

我本机ip192.168.101.248 192.168.56.3服务器发送订阅请求如上图mqtt使用的是TCP/IP网络传输所以也要经过三次握手原则。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递,也就是上面mqtt的特点:使用 TCP/IP 提供网络连接。

 

 

名词解释:SYN表示建立连接, FIN表示关闭连接, ACK表示响应, PSH表示有DATA数据传输, RST表示连接重置。

 



 
Connect 中可以看到我的发布者ID demo也就是我代码中所写的:



 

 

第二个Connect Ack 内容

 



 
可以看到是0;因为我没有设置QOS消息方法所以默认是00代表最多1次,发完就丢弃,不保证消息是否收到。下面可以参考QOS服务质量资料。

 

 

Publish message 也就是我们发送的消息了

 



 

因为这里汉字是采用8进制表示的,如果转码需要经过转为16进制每两位代表一个汉字共四位,从中间的topic就可以看出那个就是我们发送的消息了。

 

 

 

PUBACK

 


 

服务器向我们返回的信息也就是这个信息的ID号了。

 

DISCONNECT

-客户端断开连接,因为我在代码中最后执行了断开连接的方法所以会通知服务器。代码如图:

 

 

 

 

QOS 1

 

(所有QoS level 1都要在可变头部中附加一个16位的消息ID提供SUBSCRIBE(订阅)UNSUBSCRIBE(退订)消息使用。针对消息的发布,Qos level 1,意味着消息至少被传输一次。发送者若在一段时间内接收不到PUBACK消息,发送者需要打开DUB标记为1,然后重新发送PUBLISH消息。因此会导致接收方可能会收到两次PUBLISH消息)

 

因为连接的是时候可以接受到mqtt服务器的回复,在送出去消息的时候要让服务器回执发送不到客户端,这个测试环境不好测试所以就没例子。

 

 

 

QOS 2

 

 

从上图可以看出首先发布者连接mqtt服务器,然后得到服务器的回复,发布者就开始发送消息,服务器这边回复 publish received也就是告诉发布者你的消息我收到了,接着发布告诉服务器,我收到你的回复了,那条消息你可以删除了,然后服务器又回复发布者我做完了,最后发布者断开连接。

 

 

QOS 3 (mqtt 预留的信息类型待用。这里就没测试的必要了)

 

 

 

DUP flag(打开标志)

保证消息可靠传输,默认为0,只占用一个字节,表示第一次发送。不能用于检测消息重复发送等。只适用于客户端或服务器端尝试重发PUBLISH, PUBREL, SUBSCRIBE UNSUBSCRIBE消息,注意需要满足以下条件:当QoS > 0 消息需要回复确认此时,在可变头部需要包含消息ID。当值为1时,表示当前消息先前已经被传送过。

 

 

QoS(Quality of Service,服务质量)

使用两个二进制表示PUBLISH类型消息:

QoS value

bit 2

bit 1

Description

0

0

0

至多一次

发完即丢弃

<=1

1

0

1

至少一次

需要确认回复

>=1

2

1

0

只有一次

需要确认回复

=1

3

1

1

待用,保留位置

 

 

 

 

 

 

RETAIN(保持)

仅针对PUBLISH消息。不同值,不同含义:

 

 

1:表示发送的消息需要一直持久保存(不受服务器重启影响),不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。

 

 

 

 

 这里我设置为true 也就是1,测试的topictestRetain

 

 

 

这里我先让一个订阅者jieshou订阅一个testRetain,现在来测试下发布者发布一条消息的结果。这里发布者已经发布了一条消息

 



 

 已经订阅的订阅者已经接受到了消息

现在再来启动第二个订阅者订阅者叫jieshou2

 

 



 

新来的订阅者也接受到了该信息。备注:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送。

 

 

 

0:仅仅为当前订阅者推送此消息。

 

假如服务器收到一个空消息体(zero-length payload)RETAIN = 1、已存在Topic namePUBLISH消息,服务器可以删除掉对应的已被持久化的PUBLISH消息。

 



 

发送者发送一条消息给订阅方。



 

开启第二个新订阅者



 

新的订阅者没有接收到消息

 

 

 

Remaining Length(剩余长度)

在当前消息中剩余的byte(字节)数,包含可变头部和负荷(称之为内容/body,更为合适)。单个字节最大值:0111111116进制:0x7F10进制为127。单个字节为什么不能是111111110xFF)呢?因为MQTT协议规定,第八位(最高位)若为1,则表示还有后续字节存在。同时MQTT协议最多允许4个字节表示剩余长度。那么最大长度为:0xFF,0xFF,0xFF,0x7F,二进制表示为:11111111,11111111,11111111,01111111,十进制:268435455 byte=261120KB=256MB=0.25GB 四个字节之间值的范围:

 

Digits

From

To

1

0 (0x00)

127 (0x7F)

2

128 (0x80, 0x01)

16 383 (0xFF, 0x7F)

3

16 384 (0x80, 0x80, 0x01)

2 097 151 (0xFF, 0xFF, 0x7F)

4

2 097 152 (0x80, 0x80, 0x80, 0x01)

268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

 

固定头部仅定义了消息类型和一些标志位,一些消息的元数据,需要放入可变头部中。可变头部内容字节长度 + Playload/负荷字节长度 = 剩余长度,这个是需要牢记的。可变头部,包含了协议名称,版本号,连接标志,用户授权,心跳时间等内容。

消息体主要是为配合固定/可变头部命令(比如CONNECT可变头部User name标记若为1则需要在消息体中附加用户名称字符串)而存在。

CONNECT/SUBSCRIBE/SUBACK/PUBLISH等消息有消息体。PUBLISH的消息体以二进制形式对待。

我这里使用的是paho mqtt框架所以消息体中二进制转义等一系列功夫就不需要关心太多,只需要记住mqtt协议消息体最大容量和消息的表现形式就可以了。具体转义实现可以参考:http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html

 

 

 

 

当我强制关闭客户端程序的时候



 
也就是mqtt协议特点  Last Will Testament 特性通知有关各方客户端异常中断的机制。  ·

 

其他问题参考文献:http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html

 

http://blog.csdn.net/u013944791/article/details/44218471

猜你喜欢

转载自umbrellall1.iteye.com/blog/2352670