| Home | Libraries | People | FAQ | More

## Disconnecting the Client

The ``mqtt_client`` remains active until it is either destroyed or explicitly stopped. In idle mode, the ``mqtt_client`` periodically sends `PINGREQ` to the Broker to maintain a stable connection.

The proper way to stop the ``mqtt_client`` is by calling either `mqtt_client::cancel` or `mqtt_client::async_disconnect`. Invoking `mqtt_client::cancel` results in the ``mqtt_client`` closing the connection to the Broker and cancelling all outstanding asynchronous operations. On the other hand, `mqtt_client::async_disconnect` will first attempt to send a `DISCONNECT` packet [4] to the Broker to notify it about the reason for disconnection, then close the connection and cancel all outstanding asynchronous operations (equal effect as `mqtt_client::cancel`).

| Important
Regardless of the method used to stop the ``mqtt_client``, it is recommended to ensure that all the previous asynchronous operations are completed. Otherwise, they will be cancelled.

Invoking `mqtt_client::cancel` or `mqtt_client::async_disconnect` will result in a clean and graceful shutdown process. This ensures that all resources are properly released and all asynchronous operations are completed [5]. Consequently, the execution context (`boost::asio::io_context`) will stop due to a lack of work.

| Note
The ``mqtt_client``'s destructor will also call `mqtt_client::cancel`.

The following code snippet will showcase a scenario of disconnecting the ``mqtt_client`` and its interaction with other asynchronous operations.

#### Example: immediate disconnection and its impact on outstanding asynchronous operations

The following code snippet is an example of publishing a "Hello World!" message to the Broker with QoS `0`, followed by the request to disconnect the ``mqtt_client``.

    int main() {
        boost::asio::io_context ioc;

        boost::mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
        client.brokers("<your-mqtt-broker>", 1883)
            .async_run(boost::asio::detached);

        client.async_publish<boost::mqtt5::qos_e::at_most_once>(
            "<topic>", "Hello world!",
            boost::mqtt5::retain_e::no, boost::mqtt5::publish_props {},
            [](boost::mqtt5::error_code ec) {
                std::cout << ec.message() << std::endl;
            }
        );

        client.async_disconnect(boost::asio::detached);

        ioc.run();
    }

Suppose the Broker is available and the ``mqtt_client`` can successfully connect to it, then the following order of events will unfold:

1. The Client will successfully establish a connection to the Broker.
2. The Client will send a `DISCONNECT` packet with Reason Code `0x00` (`Normal Disconnection`).

It is important to note that the `PUBLISH` packet containing the "Hello World!" message will not be transmitted. As outlined in the `Packet Ordering` in Optimising communication section, `mqtt_client::async_publish` and `mqtt_client::async_disconnect` will place their corresponding packets in the queue. However, `DISCONNECT` packets are prioritised and sent exclusively, ahead of other queued packets. Therefore, the connection will terminate immediately.

If the ``mqtt_client`` cannot establish a connection to the Broker, it will be stopped after `5 seconds`, which is the amount of time it will spend trying to send the `DISCONNECT` packet to the Broker before quitting. This timeout mechanism ensures that the ``mqtt_client`` does not indefinitely wait to disconnect, preserving resources and maintaining efficient operation.

In this case, the proper way to disconnect would be to call `mqtt_client::async_disconnect` after the `mqtt_client::async_publish` has been completed.

    client.async_publish<boost::mqtt5::qos_e::at_most_once>(
        "<topic>", "Hello world!",
        boost::mqtt5::retain_e::no, boost::mqtt5::publish_props {},
        [&client](boost::mqtt5::error_code ec) {
            std::cout << ec.message() << std::endl;
            client.async_disconnect(boost::asio::detached);
        }
    );

### Restarting the Client After Disconnection

Once the ``mqtt_client`` has been successfully stopped, reactivating it is straightforward and requires invoking `mqtt_client::async_run`. This method can be called right after initiating `mqtt_client::async_disconnect`, without waiting for it to complete.

The ``mqtt_client`` is configurable again in the interval between stopping and restarting. See Configuring Your MQTT Connection for more information.

    int main() {
        boost::asio::io_context ioc;

        boost::mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
        client.brokers("<your-mqtt-broker>", 1883)
            .async_run(boost::asio::detached);

        client.async_disconnect(boost::asio::detached);

        // The Client can be reconfigured again.
        client.connect_property(boost::mqtt5::prop::session_expiry_interval, 120)
            .keep_alive(30)
            .async_run(boost::asio::detached); // Restart the Client again.

        // Use the Client...

        ioc.run();
    }

[4] The ``mqtt_client`` will attempt to send the `DISCONNECT` packet for `5 seconds`. Regardless of the outcome, the connection will be closed.

[5] All outstanding operations will complete with error code `boost::asio::error::operation_aborted`.