MQTT斷線重連
阿新 • • 發佈:2019-01-04
MQTT客戶端:org.eclipse.paho.client.mqttv3
MQTT伺服器:EMQ
MQTT伺服器官網:http://emqtt.com/
如果第一次看MQTT,可以參考:http://blog.csdn.net/whb3299065/article/details/79088928
在之前的文章中我們簡單介紹了MQTT的收發訊息,並沒有實現重連機制,我在實現重連時,發現有不少坑。經常提示
執行緒異常中斷之類的.
首先,讓我們先進行一下準備工作,我們需要先定義一個連線物件
private static MqttClient client;
//生成配置物件,使用者名稱,密碼等
public MqttConnectOptions getOptions() {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(account);
options.setPassword(password.toCharArray());
options.setConnectionTimeout(10);
options.setKeepAliveInterval(20);
return options;
}
public void connect() throws MqttException {
//防止重複建立MQTTClient例項
if (client==null) {
client = new MqttClient(host + ":" + port, clientId, new MemoryPersistence());
client.setCallback(new PushCallback(MiddlewareMqttClient.this));
}
MqttConnectOptions options = getOptions();
//判斷攔截狀態,這裡注意一下,如果沒有這個判斷,是非常坑的
if (!client.isConnected()) {
client.connect(options);
System.out.println("連線成功");
}else {//這裡的邏輯是如果連線成功就重新連線
client.disconnect();
client.connect(getOptions(options));
System.out.println("連線成功");
}
}
//監聽裝置發來的訊息
//PostConstruct確保該函式在類被初始化時呼叫
@PostConstruct
public void init() {
connect();
//getMessage是我自己封裝的一個訂閱主題的函式,對於聰明的你們,應該很簡單吧
getMessage(topic, 2);
getMessage(taskTopic, 2);
getMessage("$SYS/brokers/[email protected]/clients/#", 2);
}
由於這裡需要將連線物件獨立出來,所以專們將連線函式提取出來了,其他函式簡單貼一下程式碼,不懂的可以去查一下之前的程式碼
大家看一下上面連線物件中:client.setCallback(new PushCallback(MiddlewareMqttClient.this));
這裡MiddlewareMqttClient類為MQTT客戶端類,這裡我他自己傳入訊息回撥的構造
我們在MqttCallback 的實現類中,儲存了這個物件。
public class PushCallback implements MqttCallback {
public PushCallback() {}
MiddlewareMqttClient service;
public PushCallback(MiddlewareMqttClient service) {
this.service = service;
}
然後,我們在掉線回撥中,呼叫service的連線資訊:
//連線丟失:一般用與重連如果發生丟失,就會呼叫這裡
public void connectionLost(Throwable throwable) {
while (true){
try {//如果沒有發生異常說明連線成功,如果發生異常,則死迴圈
Thread.sleep(1000);
service.init();
break;
}catch (Exception e){
continue;
}
}
}
這樣,我們就實現了斷線重連的機制了。
下面我再來填一個坑,大家想一想,如果第一次就沒有連線成功會怎麼樣呢,,,客戶端並不算掉線,所以並不會觸發掉線重連的機制,所以我們在連線時就應該不斷連線,於是我過載了一下我的連線物件。這裡如果給定999以下引數,會只進行有限次數的重連,如果讓系統不停重連需要number>999
public void connect(int number) {
for (int i = 0; i < number||number>999; i++) {
try {
connect();
} catch (Exception e) {
e.printStackTrace();
//Thread.sleep(5000);
System.err.println("連線失敗,正在第"+i+"次嘗試");
continue;
}
return;
}
throw new RuntimeException("無法連線伺服器");
}
目前我能想到的就只有這些,測試證明,效果不錯