eclipse-paho / paho.mqtt.c

An Eclipse Paho C client library for MQTT for Windows, Linux and MacOS. API documentation: https://eclipse.github.io/paho.mqtt.c/
https://eclipse.org/paho
Other
1.98k stars 1.1k forks source link

How to gracefully know whether reconnection is successful and resubscribed topic? #1492

Open lyx10101010 opened 5 months ago

lyx10101010 commented 5 months ago

Describe the bug

How to gracefully know whether reconnection is successful and resubscribed?

To Reproduce

:one: Based on the paho_c_sub.c example, I removed all finished = 1; statements in failure type callbacks to prevent exit on failure.

:two: I added a connectionLost callback function to this example. When MQTTAsync disconnects, I can know immediately that the network is disconnected.

void connectionLost(void* context, char* cause)
{
    if (!opts.quiet)
        printf("\nConnection lost\n");
    if (cause)
        printf("     cause: %s\n", cause);
    disconnected = 1;
}

rc = MQTTAsync_setCallbacks(client, client, connectionLost, messageArrived, NULL);
if (rc != MQTTASYNC_SUCCESS)
{
    if (!opts.quiet)
        fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTAsync_strerror(rc));
    exit(EXIT_FAILURE);
}

:three: Execute command to connect to an MQTT broker and subscribe to a topic. In the original example, upon successful connection, the MQTTAsync_subscribe operation is performed in the onConnect/onConnect5 callback, continuously receiving messages from the broker.

:four: If the network disconnects, the connectionLost callback function is called; now, it's known that the network is disconnected.

:five: Since MQTTAsync internally has a reconnection mechanism, the client can reconnect successfully when the network is normal, but there are no successful connection prints, and the callback function after successful reconnection is not executed;

:bookmark: We reviewed the code and found that the callback functions were set to null, which is why the callback functions are not executed again. We looked at many related issues, but still don't quite understand how to operate;

:bookmark: Because we are using the clean_session=true flag, and we perform MQTTAsync_subscribe operations in the callback, we won't receive messages on the topic after successful connection. Although we can temporarily solve this problem with the clean_session=false flag, it's not our expected solution, as I cannot fully rely on the broker's mechanism because some brokers might support keeping sessions in memory, and if the broker restarts, session information might be lost, which I cannot rely on clean_session=false;

:bookmark: Although it's not necessarily required to execute the MQTTAsync_subscribe function in the onConnect/onConnect5 callbacks to subscribe, since I cannot immediately know the current status after a successful reconnection, I also cannot gracefully perform MQTTAsync_subscribe elsewhere. The MQTTAsync_isConnected function can determine the current status, but it requires continuous looping to check, is there a more elegant way to know that it has successfully reconnected?

Expected behavior

:one: How to gracefully know the current status? I removed all the code commented with /* Null out callback pointers so they aren't accidentally called again */, and I tested it, and it all worked successfully, the needed callbacks could be expectedly called, but I don't know if there are any other side effects, please clarify, thank you!

image

:two: How to gracefully resubscribe after being reconnected to the broker with MQTTAsync library?

Environment (please complete the following information):

icraggs commented 4 months ago

The best way is to call subscribe in the onConnect callback, if you haven't reconnected with cleansession=false.

The onConnect callback is the elegant way to know that the client has reconnected. No polling or looping, and is done in a timely manner.