Eclipse Paho MQTT Client: Как проверить существующее соединение? - PullRequest
0 голосов
/ 23 мая 2018

На веб-сайте Eclipse Paho MQTT разработчики предоставляют пример клиента (http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/pubsync.html), который выполняет следующее:

  1. Создание объекта клиента с указанными параметрами
  2. Подключить клиент с указанными параметрами подключения
  3. Опубликовать сообщение MQTT
  4. Отключить клиент
  5. Уничтожить объект клиента

Это работает хорошоесли все, что вам нужно, это опубликовать одно сообщение.

В моем коде у меня есть функция, которая содержит в значительной степени тот же код, что и в вышеупомянутом примере, однако функция вызывается повторно из main () какМне нужно публиковать большое количество сообщений одно за другим. Проблема в том, что если я использую код точно так же, как в примере, каждый раз, когда вызывается моя функция, создается новое соединение и вскоре после его уничтожения. Это происходит снова и снова иснова, если функция вызывается повторно, вызывая огромные накладные расходы.

Есть ли способ проверить,Ent объект уже создан, и если да, то не делать это снова, а использовать уже существующий?

В моем понимании, функция MQTTClient_isConnected () должна делать это: https://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/_m_q_t_t_client_8h.html#ad9e40bdb7149ee3e5d075db7f51a735fНо если я попробую это так, я получу ошибку сегментации:

if (!MQTTClient_isConnected(client)) {
    MQTTClient_create(&client, mqtt.addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    conn_opts.username = TOKEN;

    if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
        printf("\n==> Connection to MQTT Broker failed.\n");
        MQTTClient_destroy(&client);
        exit(EXIT_FAILURE);
    }
}

[EDIT]

Вот простой демонстрационный код, который лучше иллюстрирует то, что я 'Я пытаюсь выполнить:

#include <stdio.h>
#include <MQTTClient.h>

MQTTClient client;

void publish_MQTT() {
    MQTTClient_connectOptions conn_opts =  MQTTClient_connectOptions_initializer;
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    char *payload = (char *)calloc(1024, sizeof(char));

    strcpy(payload, "hello");

    printf("DEBUG_BEFORE >> MQTTClient_isConnected(client) = %d\n", MQTTClient_isConnected(client)); // DEBUG OUTPUT

    if (!MQTTClient_isConnected(client)) {
        MQTTClient_create(&client, addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
        conn_opts.keepAliveInterval = 20;
        conn_opts.cleansession = 1;
        conn_opts.username = TOKEN;

        if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
            fprintf(stderr, RED "\n==> Connection to MQTT Broker failed.\n" RESET_CL);
            MQTTClient_destroy(&client);
            free(payload);
            exit(EXIT_FAILURE);
        }
    }

    printf("DEBUG_AFTER >> MQTTClient_isConnected(client) = %d\n", MQTTClient_isConnected(client)); // DEBUG OUTPUT

    pubmsg.payload = payload;
    pubmsg.payloadlen = strlen(payload);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;

    MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
    MQTTClient_waitForCompletion(client, token, TIMEOUT);

    //MQTTClient_disconnect(client, 10000);
    //MQTTClient_destroy(&client);
    free(payload);
}

int main(void) {
    for (i=0; i<1000; i++) {
        publish_MQTT();
    }

    return 0;
}

Пожалуйста, игнорируйте тот факт, что параметр addr никогда не указывается (в моем реальном коде это так) или что довольно бесполезно указывать сообщение в функции publish_MQTT () (вмой реальный код, данные передаются из main () в эту функцию).

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Я понял: по-видимому, в исходных кодах нет ничего плохого в исходных кодах.

Оказывается, я снова и снова добавлял порт сервера MQTT к параметру addr (в разделе кода, не показанном здесь, так как я не подозревал об источнике ошибки), каждый раз, когда вызывалась функция publish_MQTT ().Это заставило строку символов addr расти и в конечном итоге превышать указанную длину, вызывая, таким образом, SegFault.

Таким образом, все работает так, как задумано:

printf("\nADDR = %s\n\n", addr); // DEBUG OUTPUT

if (!MQTTClient_isConnected(client)) {
    strcat(strcat(addr, ":"), pt); // This line needed to be placed here, not before that if block

    MQTTClient_create(&client, addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    conn_opts.username = TOKEN;

    if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
        printf("\n==> Connection to MQTT Broker failed.\n");
        MQTTClient_destroy(&client);
        free(payload);
        exit(EXIT_FAILURE);
    }
}
0 голосов
/ 25 мая 2018

Возможно, вы устанавливаете «флаг чистого сеанса», что означает: «Если ClientId представляет Клиента, уже подключенного к Серверу, то Сервер ДОЛЖЕН отключить существующего Клиента [MQTT-3.1.4-2]».(из стандарта mqtt).Таким образом, ваш клиент отключен (существующий).

Код из примера представляется повторно доступным.Похоже, что есть проблема с передачей аргумента функции.Например, если функции нужен адрес, и вы сами даете объекты.

Морзе от стандарта: «3.2.2.2 Положение присутствия сеанса: бит 0 флагов подтверждения соединения.

Если сервер принимаетсоединение с CleanSession, установленным в 1, Сервер ДОЛЖЕН установить для Session Present значение 0 в пакете CONNACK в дополнение к установке нулевого кода возврата в пакете CONNACK [MQTT-3.2.2-1].

ЕслиСервер принимает соединение с CleanSession, установленным в 0, значение, установленное в Session Present, зависит от того, имеет ли сервер уже сохраненное состояние сеанса для предоставленного идентификатора клиента. Если у сервера есть сохраненное состояние сеанса, он ДОЛЖЕН установить для Session Present значение 1 в CONNACK.пакет [MQTT-3.2.2-2]. Если у сервера нет сохраненного состояния сеанса, он ДОЛЖЕН установить для присутствия сеанса значение 0 в пакете CONNACK. Это в дополнение к установке нулевого кода возврата в пакете CONNACK ".

...