PrevUpHomeNext

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] 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] 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;

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

	client.async_publish<async_mqtt5::qos_e::at_most_once>(
		"<topic>", "Hello world!",
		async_mqtt5::retain_e::no, async_mqtt5::publish_props {},
		[](async_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<async_mqtt5::qos_e::at_most_once>(
	"<topic>", "Hello world!",
	async_mqtt5::retain_e::no, async_mqtt5::publish_props {},
	[&client](async_mqtt5::error_code ec) {
		std::cout << ec.message() << std::endl;
		client.async_disconnect(boost::asio::detached);
	}
);

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;

	async_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(async_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.


PrevUpHomeNext