mirror of
https://github.com/boostorg/mqtt5.git
synced 2025-07-29 20:17:37 +02:00
Add a chapter on disconnection
Summary: related to T12804 Reviewers: ivica Reviewed By: ivica Subscribers: miljen, iljazovic Differential Revision: https://repo.mireo.local/D28465
This commit is contained in:
@ -42,6 +42,7 @@
|
||||
[def __Asio__ [@boost:/libs/asio/index.html Boost.Asio]]
|
||||
[def __Beast__ [@boost:/libs/beast/index.html Boost.Beast]]
|
||||
[def __ASIO_PER_OP_CANCELLATION__ [@boost:/doc/html/boost_asio/overview/core/cancellation.html Per-Operation Cancellation]]
|
||||
[def __IOC__ [@boost:doc/html/boost_asio/reference/io_context.html `boost::asio::io_context`]]
|
||||
[def __POST__ [@boost:doc/html/boost_asio/reference/post.html `boost::asio::post`]]
|
||||
[def __CO_SPAWN__ [@boost:/doc/html/boost_asio/reference/co_spawn.html `boost::asio::co_spawn`]]
|
||||
[def __USE_AWAITABLE__ [@boost:/doc/html/boost_asio/reference/use_awaitable.html `boost::asio::use_awaitable`]]
|
||||
@ -114,7 +115,7 @@
|
||||
[include 03_auto_reconnect.qbk]
|
||||
[include 04_maintaining_a_stable_connection.qbk]
|
||||
[include 05_optimising_communication.qbk]
|
||||
|
||||
[include 06_disconnecting_the_client.qbk]
|
||||
|
||||
[include 10_examples.qbk]
|
||||
|
||||
|
@ -69,7 +69,7 @@ A Broker can set this value to limit the number of simultaneous QoS > 0 messages
|
||||
potentially causing QoS 0 messages to be transmitted ahead of QoS > 0 messages in the delivery order.
|
||||
|
||||
- The __DISCONNECT__ packet is sent *in a single TCP packet before any other packets* in the queue.
|
||||
[/ TODO: reference to the disconnect chapter]
|
||||
See [link async_mqtt5.disconnecting_the_client Disconnecting the client] for more information about disconnecting.
|
||||
|
||||
[endsect] [/packet_ordering]
|
||||
|
||||
|
119
doc/qbk/06_disconnecting_the_client.qbk
Normal file
119
doc/qbk/06_disconnecting_the_client.qbk
Normal file
@ -0,0 +1,119 @@
|
||||
[section:disconnecting_the_client Disconnecting the Client]
|
||||
[nochunk]
|
||||
|
||||
The __Client__ remains active until it is either destroyed or explicitly stopped.
|
||||
In idle mode, the __Client__ periodically sends __PINGREQ__ to the Broker to maintain a stable connection.
|
||||
|
||||
The proper way to stop the __Client__ is by calling either [refmem mqtt_client cancel] or [refmem mqtt_client async_disconnect].
|
||||
Invoking [refmem mqtt_client cancel] results in the __Client__ closing the connection to the Broker and cancelling all outstanding
|
||||
asynchronous operations.
|
||||
On the other hand, [refmem mqtt_client async_disconnect] will first attempt to send a __DISCONNECT__ packet
|
||||
[footnote The __Client__ will attempt to send the __DISCONNECT__ packet for `5 seconds`. Regardless of the outcome, the connection will be closed.]
|
||||
to the Broker in order to notify it about the reason for disconnection,
|
||||
then close the connection and cancel all outstanding asynchronous operations (equal effect as [refmem mqtt_client cancel]).
|
||||
|
||||
[important Regardless of the method used to stop the __Client__, it is recommended to ensure that all the previous asynchronous operations are
|
||||
completed. Otherwise, they *will be cancelled*.]
|
||||
|
||||
Invoking [refmem mqtt_client cancel] or [refmem 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 [footnote All outstanding operations will complete with error code `boost::asio::error::operation_aborted`.].
|
||||
Consequently, the execution context (__IOC__) will stop due to a lack of work.
|
||||
|
||||
[note The __Client__'s destructor will also call [refmem mqtt_client cancel]. ]
|
||||
|
||||
The following code snippet will showcase a scenario of disconnecting the __Client__ and its interaction with other
|
||||
asynchronous operations.
|
||||
|
||||
[heading 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 __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 __Client__ can successfully connect to it, then the following
|
||||
order of events will unfold:
|
||||
|
||||
# The Client will successfully establish a connection to the Broker.
|
||||
# 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 [link async_mqtt5.optimising_communication Optimising communication] section,
|
||||
[refmem mqtt_client async_publish] and [refmem 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 __Client__ cannot establish a connection to the Broker,
|
||||
it will be stopped after `5 seconds`, which is the amount of time the it will spend
|
||||
trying to send the __DISCONNECT__ packet to the Broker before quitting.
|
||||
This timeout mechanism ensures that the __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 [refmem mqtt_client async_disconnect] after the
|
||||
[refmem 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);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
[section:reusing_the_client Restarting the Client after disconnection]
|
||||
|
||||
Once the __Client__ has been successfully stopped, reactivating it is straightforward and requires invoking [refmem mqtt_client async_run].
|
||||
This method can be called right after initiating [refmem mqtt_client async_disconnect], without waiting for it to complete.
|
||||
|
||||
The __Client__ is configurable again in the interval between stopping and restarting.
|
||||
See `Customising your MQTT connection` in [link async_mqtt5.configuring_the_client Configuring the Client]
|
||||
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();
|
||||
}
|
||||
```
|
||||
|
||||
[endsect] [/reusing_the_client]
|
||||
|
||||
[endsect] [/disconnecting_the_client]
|
Reference in New Issue
Block a user