1. 程式人生 > >MQTT斷線重連

MQTT斷線重連

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("無法連線伺服器");
}

目前我能想到的就只有這些,測試證明,效果不錯