MQTT 之 paho.mqtt.c 库的自动重连的使用

0.环境

1.重连功能要点

1.1对连接选项进行如下的断开重连设置

1.2设置对应的回调

1.3 另外的补充

2.示例代码

3.补充说明


0.环境

  • centos 
  • paho.mqtt.c-1.3.10

1.重连功能要点

使用 paho.mqtt.c 库自带的内部重连逻辑进行断开重连。

1.1对连接选项进行如下的断开重连设置

MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
conn_opts.automaticReconnect = 1;//设置非零,断开自动重连,默认是0
conn_opts.minRetryInterval = 3; //单位秒,重连间隔次数,每次重新连接失败时,重试间隔都会加倍,直到最大间隔
conn_opts.maxRetryInterval = 60;//单位秒,最大重连尝试间隔

1.2设置对应的回调

//设置连接丢失回调函数:连接断开时会被调用,可以暂停当前的通信等处理操作
//注意:messageArrived回调函数必须设置,否则能编译过,但是运行报如下错误:
//Failed to set callback, return code -1
if ((rc = MQTTAsync_setCallbacks(g_client, NULL, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
{
    printf("Failed to set callback, return code %d\n", rc);
    exit(EXIT_FAILURE);
}


//设置连接成功回调函数:连接重新建立时会被调用,可以设置状态,继续通信等处理操作
if ((rc = MQTTAsync_setConnected(g_client, NULL, onConnectCallCBack)) != MQTTASYNC_SUCCESS)
{
    printf("Failed to set callback, return code %d\n", rc);
    exit(EXIT_FAILURE);
}

1.3 另外的补充

    调用 MQTTAsync_disconnect 后会导致回调函数失效,进而导致重连逻辑失效,要注意;

2.示例代码

/*******************************************************************************
 * 使用paho MQTTAsync_publish_time.c 文件修改的重连逻辑示例
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "MQTTAsync.h"

#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#include <Minwinbase.h>
#endif

#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif

#if defined(_WIN32) || defined(_WIN64)
#define snprintf _snprintf
#endif


// Better not to flood a public broker. Test against localhost.
#define ADDRESS         "tcp://localhost:1883"

#define CLIENTID        "ExampleClientTimePub"
#define TOPIC           "data/time"
#define QOS             1
#define TIMEOUT         10000L
#define SAMPLE_PERIOD   1L    // in ms,间隔1毫秒发一条消息

volatile int finished = 0;

MQTTAsync g_client;

#define MQTT_CONNECTED 1
#define MQTT_DISCONNECTED 0
volatile int g_connected = MQTT_DISCONNECTED;

void connlost(void *context, char *cause)
{
    printf("\nERROR:Connection lost,Cause: %s,Reconnecting...\n", cause);

    g_connected = MQTT_DISCONNECTED;
}
void onConnectCallCBack(void *context, char *cause)
{
    printf("Successful onConnectCallCBack\n");
    g_connected = MQTT_CONNECTED;
}

void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
    printf("Disconnect failed\n");

}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful disconnection\n");

}

void onSendFailure(void* context, MQTTAsync_failureData* response)
{
    printf("Message send failed token %d error code %d\n", response->token, response->code);

#if 0   //disconnect  会导致回调函数失效,进而导致重连逻辑失效,要注意
    MQTTAsync client = (MQTTAsync)context;
    MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;

    opts.onSuccess = onDisconnect;
    opts.onFailure = onDisconnectFailure;
    opts.context = client;
    int rc;
    if ((rc = MQTTAsync_disconnect(client, &opts)) == MQTTASYNC_SUCCESS)
    {
        printf("success to start disconnect , return code %d\n", rc);
    }
    else
    {
        printf("Failed to start disconnect, return code %d\n", rc);
    }
#endif
}
void onSend(void* context, MQTTAsync_successData* response)
{
    // This gets called when a message is acknowledged successfully.
}

void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
    printf("Connect failed, rc %d\n", response ? response->code : 0);

    g_connected = MQTT_DISCONNECTED;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful connection\n");
    g_connected = MQTT_CONNECTED;
}

int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message)
{
    /* not expecting any messages */
    printf("Message arrived\n");
    printf("    topic: %s\n", topicName);
    printf("    message: %.*s\n", message->payloadlen, (char*)message->payload);
    MQTTAsync_freeMessage(&message);
    MQTTAsync_free(topicName);
    return 1;
}

int64_t getTime(void)
{
    #if defined(_WIN32)
        FILETIME ft;
        GetSystemTimeAsFileTime(&ft);
        return ((((int64_t) ft.dwHighDateTime) << 8) + ft.dwLowDateTime) / 10000;
    #else
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        return ((int64_t) ts.tv_sec * 1000) + ((int64_t) ts.tv_nsec / 1000000);
    #endif
}

int main(int argc, char* argv[])
{

    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;

    MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
    MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;

    int rc;

    if ((rc = MQTTAsync_create(&g_client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to create client object, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    //设置连接丢失回调
    if ((rc = MQTTAsync_setCallbacks(g_client, NULL, connlost, NULL, NULL)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to set callback, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    //设置连接成功回调
    if ((rc = MQTTAsync_setConnected(g_client, NULL, onConnectCallCBack)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to set callback, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    conn_opts.onSuccess = onConnect;
    conn_opts.onFailure = onConnectFailure;
    conn_opts.context = g_client;

    //断开重连设置
    conn_opts.automaticReconnect = 1;//设置非零,断开自动重连
    conn_opts.minRetryInterval = 3; //单位秒,重连间隔次数,每次重新连接失败时,重试间隔都会加倍,直到最大间隔
    conn_opts.maxRetryInterval = 60;//单位秒,最大重连尝试间隔

    if ((rc = MQTTAsync_connect(g_client, &conn_opts)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to start connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    while (!g_connected) {
        #if defined(_WIN32)
            Sleep(100);
        #else
            usleep(100000L);
        #endif
    }

    while (!finished) 
    {
        if(MQTT_CONNECTED == g_connected)
        {
            int64_t t = getTime();

            char buf[256];
            int n = snprintf(buf, sizeof(buf), "%lld", (long long) t);
            printf("SEND:%s\n", buf);

            pub_opts.onSuccess = onSend;
            pub_opts.onFailure = onSendFailure;
            pub_opts.context = g_client;

            pubmsg.payload = buf;
            pubmsg.payloadlen = n;
            pubmsg.qos = QOS;
            pubmsg.retained = 0;

            if ((rc = MQTTAsync_sendMessage(g_client, TOPIC, &pubmsg, &pub_opts)) != MQTTASYNC_SUCCESS)
            {
                printf("Failed to start sendMessage, return code %d\n", rc);
                g_connected = MQTT_DISCONNECTED;
            }
        }
        else
        {
            printf("mqtt disconnected...\n");
            usleep(1000 * 1000);
        }

        #if defined(_WIN32)
            Sleep(SAMPLE_PERIOD);
        #else
            usleep(SAMPLE_PERIOD * 1000);
        #endif
    }


    MQTTAsync_destroy(&g_client);
    return rc;
}

3.补充说明

以上操作在源码目录的 paho.mqtt.c-1.3.10/docs/MQTTAsync/html/auto_reconnect.html 中有说明,使用浏览器打开,如下图位置,有对应的说明:

就是第一节里的总结,建议到对应的设置参数源码注释中看看,也有对应的说明。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值