物联网最近曝光率越来越高。虽然HTTP是网页的事实标准,不过机器之间(Machine-to-Machine,M2M)的大规模沟通需要不同的模式:之前的请求/回答模式不再合适,取而代之的是发布/订阅(Publish/Subscribe)模式。这就是轻量级、可扩展的MQTT(Message Queuing Telemetry Transport)可以施展拳脚的舞台。
MQTT协议文档https://www.gitbook.com/book/mcxiaoke/mqtt-cn/details
采用WireShark抓包工具分析MQTT消息,参考http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718063分析协议包
首先运行工程
[java] view plain copy print?import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class SubScriberExample {
/**
* @param args
*/
public static void main(String[] args) {
String[] topicFilters ={"topic1","topic2"} ;
String broker = "tcp://192.168.80.196:1883" ;
String clientId = "paho-1" ;
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId,persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession( false );
System. out .println( "Connecting to broker: " + broker);
sampleClient.connect(connOpts);
System. out .println( "Connected" );
sampleClient.setCallback(new CustomMQTTCallBack());
sampleClient.subscribe(topicFilters,new int[]{1,1});
System. out .println( "Subscribe success for: "+topicFilters.toString());
} catch (MqttException me) {
System. out .println( "reason " + me.getReasonCode());
System. out .println( "msg " + me.getMessage());
System. out .println( "loc " + me.getLocalizedMessage());
System. out .println( "cause " + me.getCause());
System. out .println( "excep " + me);
me.printStackTrace();
}
}
}
当运行客户端之后通过抓取TCP数据包
- 固定头部
SUBSCRIBE 固定头部的消息格式见下表
从上图的抓包程序得到的数据可知,固定头部的16进制为:82 14
结合上面的表1,我们可知其具体含义如下:
82---1000 0010 表示连接的请求是Subscribe
14--1*16+4=20 表示后面将会跟着20个字节
2.可变头部
从上图的抓包程序得到的数据可知,可变头部的16进制为:00 01
结合上面的表2,我们可知其具体含义如下:
00 01 ---表示当前的Package的ID是1
3.负载部分
SUBSCRIBE 负载部分的消息格式见下表,负载部分主要指定订阅的主题(Topic)的名称以及每个订阅的主题对应的QoS级别(总共三种类型的值:0,1,2),需要注意的是,在负载部分,一次可以订阅多个主题。
从上图的抓包程序得到的数据可知,负载部分实际捕获的数据为:00 06 74 6f 70 69 63 31 01 00 06 74 6f 70 69 63 32 01 因为总共有两个主题:topic1 和topic2,所以我们拿第一个主题(topic1)来分析就行了,后面的Topic类似.
00 06 代表这个topic的长度是6个字节
74 6f 70 69 63 31 代表 topic1
01 代表QoS为1
从此看出MQTT数据包并不复杂,掌握了就能看懂。