MQTT遺願(last will) paho.mqtt實現

1、 MQTT遺囑

MQTT 能夠設置遺囑,客戶端在鏈接Broker的時候將遺囑內容(也是topic + payload形式,遺囑也有一個主題)發送給Broker並保存在Broker中,當客戶端由於非正常緣由斷開與Broker的鏈接時,Broker會將遺囑信息發送給訂閱了該主題(訂閱遺囑的主題)的客戶端。ios

客戶端正常調用DISCONNECT斷開鏈接時屬於正常斷開鏈接,Broker不會發送遺囑,並且會將遺囑從Broker中刪除。網絡

遺囑消息發佈的條件,包括但不限於:session

  • 服務端檢測到了一個I/O錯誤或者網絡故障。
  • 客戶端在爆出鏈接(Keep Alive)的時間內未能通信。
  • 客戶端沒有發送DISCONNECT保溫直接關閉了網絡鏈接。
  • 因爲協議錯誤服務端關閉了網絡鏈接。

一旦被髮布或者服務端收到了客戶端發送的DISCONNECT報文,遺囑消息就必須從存儲的會
話狀態中移除。tcp

2、基於paho.mqtt.c實現遺囑功能

網上關於遺囑的介紹很多,可是實際的例子卻不多,按理說 paho.mqtt.c 這個庫用的挺多的,可是也沒找到相關的例子,本身寫了一個,其實也挺簡單的,代碼以下:函數

// mqtt-last-will.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include <iostream>
#include <MQTTClient.h>


#define ADDRESS     "tcp://127.0.0.1:1883"   // broker 地址
#define CLIENTID    "mqtt_test_client"  // client id
#define TOPIC       "MQTT Examples"     // 正常發佈測試的主題
#define PAYLOAD     "Hello World!"      //正常發佈時的payload
#define QOS         1
#define TIMEOUT     10000L

// last will topic and payload
#define LAST_WILL_TOPIC "Iamdie"           // 遺囑主題
#define LAST_WILL_MSG "I am really die."   //遺囑的內容


int main()
{
	MQTTClient client;
	MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
	//MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;  //不使用ssl加密
	MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;

	int nRet = MQTTCLIENT_SUCCESS;
	nRet = MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
	if(nRet != MQTTCLIENT_SUCCESS)
	{
         printf("Failed to create client, return code %d\n", nRet);
		 return -1;
    }
	conn_opts.keepAliveInterval = 20;
	conn_opts.cleansession = 1;
	//conn_opts.ssl = &ssl_opts;    // ssl config   //不使用ssl加密

	// last will config  遺囑設置
	//will_opts.retained = 1;  //retained = 1 時, broker會一直保留消息,這裏不須要,使用默認的0就行
	will_opts.topicName = LAST_WILL_TOPIC;
	will_opts.message = LAST_WILL_MSG;
	conn_opts.will = &will_opts;

	// 鏈接broker
	nRet = MQTTClient_connect(client, &conn_opts);
	if (nRet != MQTTCLIENT_SUCCESS)
	{
		printf("Failed connect to broker, return code %d\n", nRet);
		return -1;
	}

	// 測試發佈消息
	MQTTClient_message PubMsg = MQTTClient_message_initializer;
	MQTTClient_deliveryToken token;
	PubMsg.payload = (void*)PAYLOAD;
	PubMsg.payloadlen = (int)strlen(PAYLOAD);
	PubMsg.qos = QOS;
	PubMsg.retained = 0;
	if ((nRet = MQTTClient_publishMessage(client, TOPIC, &PubMsg, &token)) != MQTTCLIENT_SUCCESS)
	{
		printf("Failed to publish message, return code %d\n", nRet);
		return -1;
	}

	nRet = MQTTClient_waitForCompletion(client, token, TIMEOUT);

	// 這裏正常執行 MQTTClient_disconnect 時是不發送遺囑的,須要測試發送遺囑的時候將disconnect 屏蔽掉,直接destroy就能夠
	if ((nRet = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
	{
		printf("Failed to disconnect, return code %d\n", nRet);
	}

	MQTTClient_destroy(&client);
	return 0;
}
相關文章
相關標籤/搜索