Skip to content
Takatoshi Kondo edited this page Feb 17, 2021 · 2 revisions

This is reconnecting code:

#include <iostream>
#include <mqtt_client_cpp.hpp>

int main() {
    boost::asio::io_context ioc;
    auto c = mqtt::make_sync_client(ioc, "test.mosquitto.org", 1883);

    c->set_client_id("cid1");
    c->set_keep_alive_sec(5);
    c->set_clean_session(true);

    boost::asio::steady_timer tim(ioc);
    std::function<void()> reconnect;
    reconnect =
        [&] {
            // wait 3 seconds and connect again
            tim.expires_after(std::chrono::seconds(3));
            tim.async_wait(
                [&]
                (boost::system::error_code const& ec) {
                    if (!ec) {
                        // timer fired
                        std::cout << "try connect again" << std::endl;
                        mqtt::error_code ec;
                        c->connect(ec); // connect again
                        if (ec) {
                            std::cout << "error " << ec.message() << std::endl;
                            reconnect();
                        }
                    }
                }
            );
        };

    c->set_connack_handler(
        [&c](bool sp, mqtt::connect_return_code connack_return_code){
            std::cout << "Connack handler called" << std::endl;
            std::cout << "Session Present: " << std::boolalpha << sp << std::endl;
            std::cout << "Connack Return Code: " << connack_return_code << std::endl;
            if (connack_return_code == mqtt::connect_return_code::accepted) {
                c->subscribe("topic1", mqtt::qos::at_most_once);
            }
            return true;
        }
    );
    c->set_close_handler(
        [&] {
            std::cout << "connection closed" << std::endl;
            reconnect();
        }
    );
    c->set_error_handler(
        [&]
        (boost::system::error_code const& ec) {
            std::cout << "connection error " << ec.message() << std::endl;
            reconnect();
        }
    );

    std::cout << "try connect" << std::endl;

    mqtt::error_code ec;
    c->connect(ec);
    if (ec) {
        std::cout << "error " << ec.message() << std::endl;
        reconnect();
    }
    ioc.run();
}

There are three points to reconnect.

  1. Error before MQTT connection is established. It is typically happened by TCP TLS WebSocket layer error. This error is reported by connect(ec) error code. If you don't pass the ec then connect() throws exception. You can test it by replacing "test.mosquitto.org" with invalid host name.
  2. Gracefully disconnected by the broker after MQTT connection established. This is reported by set_close_handler().
  3. Connection error is happened after MQTT connection established. This is reported by set_error_handler(). You can test it by executing sudo ip link set down eth0. eth0 is network device name. You can recover the network connection by sudo ip link set up eth0. You can know your network device name by ls /sys/class/net.
    boost::asio::steady_timer tim(ioc);
    std::function<void()> reconnect;
    reconnect =
        [&] {
            // wait 3 seconds and connect again
            tim.expires_after(std::chrono::seconds(3));
            tim.async_wait(
                [&]
                (boost::system::error_code const& ec) {
                    if (!ec) {
                        // timer fired
                        std::cout << "try connect again" << std::endl;
                        mqtt::error_code ec;
                        c->connect(ec); // connect again
                        if (ec) {
                            std::cout << "error " << ec.message() << std::endl;
                            reconnect();
                        }
                    }
                }
            );
        };

This is reconnecting code. The error situation usually continues several seconds. So this code wait 3 seconds before trying reconnect. The reconnect method is very simple. Call connect() as the same as the first connection.