简介
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。
三种消息发布服务质量:
-
"至多一次",消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。
-
"至少一次",确保消息到达,但消息重复可能会发生。
-
"只有一次",确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。
MQTT原理
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:
-
(1)Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);
-
(2)payload,可以理解为消息的内容,是指订阅者具体要使用的内容。
在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。MQTT数据包结构如下:
-
(1)固定头(Fixed header)。存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。
-
(2)可变头(Variable header)。存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。
-
(3)消息体(Payload)。存在于部分MQTT数据包中,表示客户端收到的具体内容。
MQTT在Java中应用
MQTT的应用一般需要MQTT服务器,比如mosquito或EMQX服务软件,MQTT客户端和代理服务器可以使用代码实现。
安装mqtt服务软件
从 https://www.emqx.io/cn/mqtt/public-mqtt5-broker下载MQTT Broker。
这里我使用的windows系统,下载对应版本工具:emqx-windows-v4.1-rc.2.zip
下载好后,解压目录如下:
启动MQTT服务器
启动CMD窗口,进入到mqtt安装目录下的bin目录,运行以下指令:
第一条是启动;第二条是查看运行状态。
MQTTClient.java文件
EMQX控制台
EMQX提供了控制台配置服务,可以配置mqtt和使用工具。
在浏览器中输入: http://127.0.0.1:18083,登录账号:admin,密码:public。进入Web管理控制台。如下图所示:
在Maven项目pom.xml加入如下依赖
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.0</version>
</dependency>
MQTTClient.java文件
public static void main(String... args) {
try {
// host为主机名,clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,
// MemoryPersistence设置clientid的保存形式,默认为以内存保存
MqttClient mqttClient = new MqttClient("tcp://127.0.0.1:61613", "client", new MemoryPersistence());
// 配置参数信息
MqttConnectOptions options = new MqttConnectOptions();
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,
// 这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(true);
// 设置用户名
options.setUserName("admin");
// 设置密码
options.setPassword("public".toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(10);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(20);
// 连接
mqttClient.connect(options);
// 订阅
mqttClient.subscribe("test");
// 设置回调
mqttClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable throwable) {
System.out.println("connectionLost");
}
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
System.out.println("Topic: " + s + " Message: " + mqttMessage.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
// 创建消息
MqttMessage message = new MqttMessage("hello World!".getBytes());
// 设置消息的服务质量
message.setQos(qos);
// 发布消息
mqttClient.publish("test", message);
// 断开连接
mqttClient.disconnect();
// 关闭客户端
mqttClient.close();
} catch (Exception e) {
e.printStackTrace();
}
}
运行代码就通过mqtt可以发送和接收消息。在实际应用中会有多个客户端,可以使用多线程的方法模拟多个客户端,进行消息的发送和接收。