简体   繁体   中英

Eclipse Paho MQTT Client: How to check for existing connection?

On the Eclipse Paho MQTT website, the developers provide a client example ( http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/pubsync.html ) that does the following:

  1. Create a client object with the specified parameters
  2. Connect the client with the specified connection options
  3. Publish a MQTT message
  4. Disconnect the client
  5. Destroy the client object

This works well if all you want is to publish one single message.

In my code, I have a function that contains pretty much the same code as in the aforementioned example, however, the function is called repeatedly from main() as I need to publish a large number of messages one after another. The problem is, if I use the code exactly as in the example, every time my function is called a new connection is created and shortly after destroyed. This happens again and again and again as long as the function is called repeatedly, causing a huge overhead.

Is there a way to check whether a client object has already been created, and if so, don't do it again but use the existing one?

In my understanding, the MQTTClient_isConnected() function is supposed to do that: https://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/_m_q_t_t_client_8h.html#ad9e40bdb7149ee3e5d075db7f51a735f But if I try it like this, I get a Segmentation fault:

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]

Here is a simple demo code that better illustrates what I'm trying to accomplish:

#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;
}

Please ignore the fact that the addr parameter is never specified (in my real code it is) or that it is pretty useless specifying a message in the publish_MQTT() function (in my real code, data is passed from main() to that function).

I figured it out: Apparently, there is absolutely nothing wrong with the example codes in the original posting.

It turns out I was appending the port of the MQTT server to the addr parameter again and again (in a section of the code not shown here as I didn't suspect the source of the error to be there), every time the publish_MQTT() function was called. This made the addr char string grow and eventually exceed the specified length, thus causing the SegFault.

This way everything works just as intended:

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);
    }
}

Probably you are setting up "clean session flag", what's mean: " If the ClientId represents a Client already connected to the Server then the Server MUST disconnect the existing Client [MQTT-3.1.4-2]." (from mqtt standard). So you client is disconnected (the existing one).

Code from example seems to be reasobable. It looks like there is problem with passing function argument. For example if function needed address, and you are giving objects itself.

Morze from standard: "3.2.2.2 Session Present Position: bit 0 of the Connect Acknowledge Flags.

If the Server accepts a connection with CleanSession set to 1, the Server MUST set Session Present to 0 in the CONNACK packet in addition to setting a zero return code in the CONNACK packet [MQTT-3.2.2-1].

If the Server accepts a connection with CleanSession set to 0, the value set in Session Present depends on whether the Server already has stored Session state for the supplied client ID. If the Server has stored Session state, it MUST set Session Present to 1 in the CONNACK packet [MQTT-3.2.2-2]. If the Server does not have stored Session state, it MUST set Session Present to 0 in the CONNACK packet. This is in addition to setting a zero return code in the CONNACK packet".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM