mirror of
https://github.com/boostorg/mqtt5.git
synced 2025-07-29 20:17:37 +02:00
Document LoggerType concept and improve Getting Started chapter
Summary: related to T15252, T15261, T15263, #24 - documented LoggerType concept - configuring the client chapter changed to getting started chapter with new additions: - code examples for each section (choosing underlying type, configuring the client, and using it) - added a secion on debugging the client using our logger implementation - minor fixes related to reviewer's suggestions Reviewers: ivica Reviewed By: ivica Subscribers: iljazovic, miljen Differential Revision: https://repo.mireo.local/D32487
This commit is contained in:
@ -37,6 +37,7 @@
|
||||
[template mqttlink[id text][@https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc[id] [text]]]
|
||||
|
||||
[def __OPENSSL__ [@https://www.openssl.org/ OpenSSL]]
|
||||
[def __HIVEMQ__ [@https://www.hivemq.com/ HiveMQ]]
|
||||
|
||||
[def __CompletionToken__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.completion_tokens_and_handlers CompletionToken]]
|
||||
[def __Executor__ [@boost:/doc/html/boost_asio/reference/Executor1.html Executor]]
|
||||
@ -44,6 +45,7 @@
|
||||
[def __StreamType__ [reflink StreamType]]
|
||||
[def __TlsContext__ [reflink TlsContext]]
|
||||
[def __is_authenticator__ [reflink is_authenticator]]
|
||||
[def __LoggerType__ [reflink LoggerType]]
|
||||
|
||||
[def __Boost__ [@https://www.boost.org/ Boost]]
|
||||
[def __Asio__ [@boost:/libs/asio/index.html Boost.Asio]]
|
||||
@ -58,6 +60,7 @@
|
||||
[def __STRAND__ [@boost:doc/html/boost_asio/reference/io_context__strand.html `boost::asio::io_context::strand`]]
|
||||
[def __DISPATCH__ [@boost:doc/html/boost_asio/reference/dispatch.html `boost::asio::dispatch`]]
|
||||
[def __POST__ [@boost:doc/html/boost_asio/reference/post.html `boost::asio::post`]]
|
||||
[def __ASYNC_IMMEDIATE__ [@https://www.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/async_immediate.html `boost::asio::async_immediate`]]
|
||||
[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`]]
|
||||
[def __USE_FUTURE__ [@boost:/doc/html/boost_asio/reference/use_future.html `boost::asio::use_future`]]
|
||||
@ -125,16 +128,27 @@
|
||||
[def __REASON_CODES__ [reflink2 Reason_codes `Reason Codes`]]
|
||||
[def __ERROR_HANDLING__ [reflink2 Error_handling `Error handling`]]
|
||||
|
||||
[import ../../example/hello_world_over_tcp.cpp]
|
||||
[import ../../example/hello_world_over_tls.cpp]
|
||||
[import ../../example/hello_world_over_websocket_tcp.cpp]
|
||||
[import ../../example/hello_world_over_websocket_tls.cpp]
|
||||
[import ../../example/publisher.cpp]
|
||||
[import ../../example/receiver.cpp]
|
||||
[import ../../example/multiflight_client.cpp]
|
||||
[import ../../example/timeout_with_parallel_group.cpp]
|
||||
[import ../../example/timeout_with_awaitable_operators.cpp]
|
||||
[import ../../example/hello_world_in_multithreaded_env.cpp]
|
||||
[import ../../example/hello_world_in_coro_multithreaded_env.cpp]
|
||||
|
||||
[include 01_intro.qbk]
|
||||
[include 02_configuring_the_client.qbk]
|
||||
[include 02_getting_started.qbk]
|
||||
[include 03_auto_reconnect.qbk]
|
||||
[include 04_maintaining_a_stable_connection.qbk]
|
||||
[include 05_optimising_communication.qbk]
|
||||
[include 06_disconnecting_the_client.qbk]
|
||||
[include 07_asio_compliance.qbk]
|
||||
[include 11_multithreading.qbk]
|
||||
|
||||
[include 15_examples.qbk]
|
||||
[include 12_examples.qbk]
|
||||
|
||||
[include examples/Examples.qbk]
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:configuring_the_client Configuring the Client]
|
||||
[section:getting_started Getting Started]
|
||||
[nochunk]
|
||||
|
||||
This section guides you through the steps to properly configure the __Client__ to establish a connection with your chosen MQTT Broker.
|
||||
@ -14,7 +14,7 @@ Instead, it features a function that will start the Client (see [refmem mqtt_cli
|
||||
All configuration of the __Client__ must be finalised before invoking [refmem mqtt_client async_run].
|
||||
Upon calling this function, the __Client__ makes its initial attempt to connect.
|
||||
|
||||
[section:transport_protocol Choosing a suitable transport protocol]
|
||||
[section:transport_protocol Choosing a Suitable Transport Protocol]
|
||||
|
||||
The initial step is selecting an appropriate transport protocol for your MQTT connection.
|
||||
|
||||
@ -25,23 +25,19 @@ and WebSocket over TCP/IP and TLS/SSL.
|
||||
|
||||
MQTT Brokers come in various implementations and support different transport protocols.
|
||||
Therefore, it is important to familiarise yourself with the protocols your chosen Broker supports.
|
||||
Additionally, gather any necessary details such as certificate authority, client certificate, or private keys,
|
||||
Additionally, gather any necessary details, such as certificate authority, client certificate, or private keys,
|
||||
which might be required for establishing a secure connection.
|
||||
|
||||
The upcoming examples will demonstrate the configuration and the publishing of a "Hello World!" application message at `QoS` 0,
|
||||
using various transport protocols:
|
||||
In this example, we choose TCP/IP as the underlying protocol to initialize the __Client__.
|
||||
|
||||
* [link async_mqtt5.hello_world_over_tcp hello_world_over_tcp.cpp]
|
||||
* [link async_mqtt5.hello_world_over_tls hello_world_over_tls.cpp]
|
||||
* [link async_mqtt5.hello_world_over_websocket_tcp hello_world_over_websocket_tcp.cpp]
|
||||
* [link async_mqtt5.hello_world_over_websocket_tls hello_world_over_websocket_tls.cpp]
|
||||
[init_tcp_client]
|
||||
|
||||
[endsect] [/transport_protocol]
|
||||
|
||||
[section:customisation Customising your MQTT connection]
|
||||
[section:configuration Configuring Your MQTT Connection]
|
||||
|
||||
The __Client__ offers a variety of functions for customising your MQTT connection settings.
|
||||
These functionalities include:
|
||||
The __Client__ offers a variety of functions for configuring your MQTT connection settings.
|
||||
These functionalities include:
|
||||
|
||||
* *Specifying a list of Brokers:* You *must* use this function to assign a list of Brokers that the __Client__ will try to connect to (see [refmem mqtt_client brokers]).
|
||||
The __Client__ allows for the specification of multiple Brokers for the connections.
|
||||
@ -52,13 +48,22 @@ Listing Brokers from different clusters may lead to inconsistencies between MQTT
|
||||
* *Assign a custom user-implemented authenticator:* The custom authentication will be used for __ENHANCED_AUTH__ ([refmem mqtt_client authenticator]).
|
||||
* *Defining CONNECT Packet Properties:* Specify properties that will be included in the __CONNECT__ packet sent during connection initiation (see [refmem mqtt_client connect_property] and [refmem mqtt_client connect_properties]).
|
||||
|
||||
We will connect to the __HIVEMQ__'s public Broker at `broker.hivemq.com`, which listens for MQTT connections on the default TCP/IP port 1883.
|
||||
Additionally, we will set the Client Identifier to `async_mqtt5_tester` using the [refmem mqtt_client credentials] function.
|
||||
This is not strictly mandatory, as some Brokers allow anonymous connections.
|
||||
|
||||
After configuring the `mqtt_client`, we call the [refmem mqtt_client async_run] function.
|
||||
This starts the process of establishing a connection with the Broker.
|
||||
|
||||
[configure_tcp_client]
|
||||
|
||||
It is important to note that these configurations apply to every Broker listed in [refmem mqtt_client brokers].
|
||||
To modify any configuration parameters, you must first stop the __Client__ using [refmem mqtt_client cancel] or [refmem mqtt_client async_disconnect].
|
||||
Afterwards, you can re-apply the configurations and restart the __Client__ with [refmem mqtt_client async_run].
|
||||
|
||||
[endsect] [/customisation]
|
||||
[endsect] [/configuration]
|
||||
|
||||
[section:establishing_a_connection Establishing a connection]
|
||||
[section:establishing_a_connection Establishing a Connection]
|
||||
|
||||
The __Client__ initiates a connection with the first Broker from the list of Brokers assigned using [refmem mqtt_client brokers].
|
||||
A single attempt at connecting involves several steps:
|
||||
@ -87,4 +92,41 @@ and `jitter` is a randomly chosen value between `-500ms` to `500ms`, intended to
|
||||
|
||||
[endsect] [/establishing_a_connection]
|
||||
|
||||
[endsect] [/configuring_the_client]
|
||||
[section:using_the_client Using the Client]
|
||||
|
||||
After calling [refmem mqtt_client async_run], you can now use the Client according to your application needs.
|
||||
In this case, we will publish a "Hello World!" message to `async-mqtt5/test` topic with Quality of Service 0 (at most once) using the [refmem mqtt_client async_publish] function.
|
||||
|
||||
[publish_hello_world]
|
||||
|
||||
You can find the full program listing for this chapter at the link below:
|
||||
|
||||
* [link async_mqtt5.hello_world_over_tcp hello_world_over_tcp.cpp]
|
||||
|
||||
Additional "Hello World!" examples for different underlying transport protocols can be found here:
|
||||
|
||||
* [link async_mqtt5.hello_world_over_tls hello_world_over_tls.cpp]
|
||||
* [link async_mqtt5.hello_world_over_websocket_tcp hello_world_over_websocket_tcp.cpp]
|
||||
* [link async_mqtt5.hello_world_over_websocket_tls hello_world_over_websocket_tls.cpp]
|
||||
|
||||
[endsect] [/using_the_client]
|
||||
|
||||
[section:debugging Debugging the Client]
|
||||
|
||||
If you encounter configuration or connection issues, you can use our logging mechanism to debug problems.
|
||||
The __Client__ introduces a __LoggerType__ as its third template parameter, which specifies the type used for logging events within the __Client__.
|
||||
|
||||
The __Self__ library provides a built-in [ghreflink include/async_mqtt5/logger.hpp logger] implementation that outputs operation results to stderr.
|
||||
This logger outputs detailed information about each step in the connection process, including DNS resolution, TCP connection, TLS handshake, WebSocket handshake, and MQTT handshake.
|
||||
To enable this functionality, construct the __Client__ with an instance of this logger class:
|
||||
|
||||
[!c++]
|
||||
// Since we are not establishing a secure connection, set the TlsContext template parameter to std::monostate.
|
||||
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket, std::monostate /* TlsContext */, async_mqtt5::logger> client(
|
||||
ioc, {} /* tls_context */, async_mqtt5::logger(async_mqtt5::log_level::debug)
|
||||
);
|
||||
|
||||
|
||||
[endsect] [/debugging]
|
||||
|
||||
[endsect] [/getting_started]
|
@ -4,7 +4,7 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:auto_reconnect Built-in auto-reconnect and retry mechanism]
|
||||
[section:auto_reconnect Built-in Auto-Reconnect and Retry Mechanism]
|
||||
[nochunk]
|
||||
|
||||
The auto-reconnect and retry mechanism is a key feature of the __Self__ library.
|
||||
@ -54,19 +54,19 @@ and [refmem mqtt_client async_disconnect]).
|
||||
|
||||
[endsect] [/sentry]
|
||||
|
||||
[section:cons Considerations and limitations]
|
||||
[section:cons Considerations and Limitations]
|
||||
|
||||
The integrated auto-reconnect and retry mechanism greatly improves the user experience
|
||||
by simplifying complex processes and ensuring continuous connections.
|
||||
However, it is important to be mindful of certain limitations and considerations associated with this feature.
|
||||
|
||||
[heading Delayed handler invocation]
|
||||
[heading Delayed Handler Invocation]
|
||||
|
||||
During extended periods of __Client__ downtime, the completion handlers for asynchronous functions,
|
||||
such as those used in [refmem mqtt_client async_publish], may face considerable delays before invocation.
|
||||
This can result in users being left in the dark regarding the status of their requests due to the absence of prompt feedback on the initiated actions.
|
||||
|
||||
[heading Concealing configuration-related issues]
|
||||
[heading Concealing Configuration-Related Issues]
|
||||
|
||||
The __Client__ will always try to reconnect to the Broker(s) regardless of the reason why the connection was previously closed.
|
||||
This is desirable behaviour when the connection gets dropped due to underlying stream transport issues,
|
||||
@ -93,10 +93,10 @@ By design, one of the main functional requirements of the __Client__ was to hand
|
||||
If the decision for reconnection were left to the user, then the user would need to handle all those error states manually,
|
||||
which would dramatically increase the complexity of the user's code, not to mention how difficult it would be to cover all possible error states.
|
||||
|
||||
The proposed approach for detecting configuration errors in the __Client__ is to use some simple logging facility during development.
|
||||
Log lines should be injected directly into the __Client__ code (typically in the connect_op.hpp file), and logs would uncover misconfigurations (if any).
|
||||
The proposed approach for detecting configuration errors in the __Client__ is to use our logging mechanism as described
|
||||
in [link async_mqtt5.getting_started.debugging Debugging the Client]
|
||||
|
||||
[heading Increased resource consumption]
|
||||
[heading Increased Resource Consumption]
|
||||
|
||||
The __Client__ is designed to automatically buffer requests that are initiated while it is offline.
|
||||
During extended downtime or when a high volume of requests accumulates, this can lead to an increase in memory usage.
|
||||
|
@ -4,7 +4,7 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:connection_maintenance Maintaining a stable connection]
|
||||
[section:connection_maintenance Maintaining a Stable Connection]
|
||||
[nochunk]
|
||||
|
||||
This chapter delves into the strategies used by the __Client__ to sustain a stable connection with the Broker.
|
||||
@ -33,14 +33,14 @@ Use [refmem mqtt_client keep_alive] function during the __Client__ configuration
|
||||
Otherwise, the __Client__ defaults to a `Keep Alive` period of `60 seconds`.
|
||||
|
||||
[note
|
||||
The MQTT does not use the TCP's built-in keep-alive mechanism as it is inflexible and limited in that it can be configured solely at the operating system level.
|
||||
The MQTT protocol does not use the TCP's built-in keep-alive mechanism as it is inflexible and limited in that it can be configured solely at the operating system level.
|
||||
The default time a connection must be idle before sending the first keep-alive packet is typically set to 2 hours,
|
||||
exceeding the tolerances of most MQTT applications.
|
||||
]
|
||||
|
||||
[endsect] [/keep_alive]
|
||||
|
||||
[section:half_open_connections Detecting and handling half-open connections]
|
||||
[section:half_open_connections Detecting and Handling Half-open Connections]
|
||||
|
||||
Ensuring the integrity and stability of network connections is a complex task,
|
||||
given the number of potential disruptions such as software anomalies,
|
||||
|
@ -4,7 +4,7 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:optimising_communication Optimising communication]
|
||||
[section:optimising_communication Optimising Communication]
|
||||
[nochunk]
|
||||
|
||||
This chapter provides a detailed breakdown of how __Client__ optimises its communications with the Broker
|
||||
@ -12,7 +12,7 @@ with multiflight mode for simultaneous message handling and strategies for effic
|
||||
These techniques are key to getting the most out of MQTT in scenarios demanding fast and
|
||||
dependable message delivery, all while meeting the protocol's quality of service requirements and network efficiency standards.
|
||||
|
||||
[section:multiflight The multiflight mode]
|
||||
[section:multiflight The Multiflight Mode]
|
||||
|
||||
The __Self__ library introduces a multiflight feature.
|
||||
This allows the initiation of multiple asynchronous requests simultaneously, without waiting for the completion of the previous requests.
|
||||
@ -40,7 +40,7 @@ Source: [link async_mqtt5.multiflight_client multiflight_client.cpp]
|
||||
|
||||
[endsect] [/multiflight]
|
||||
|
||||
[section:packet_queuing Efficient bandwidth usage with packet queuing]
|
||||
[section:packet_queuing Efficient Bandwidth Usage With Packet Queuing]
|
||||
|
||||
The __Client__ employs a strategic queuing mechanism crucial in optimising network usage and performance for the user's requests.
|
||||
This mechanism bundles multiple MQTT packets for transmission within a single TCP packet whenever feasible
|
||||
@ -62,7 +62,7 @@ if possible [footnote The Broker's `Receive Maximum` is equal to or greater than
|
||||
|
||||
[endsect] [/packet_queuing]
|
||||
|
||||
[section:packet_ordering Packet ordering]
|
||||
[section:packet_ordering Packet Ordering]
|
||||
|
||||
The __Client__ uses a packet ordering mechanism to manage the queued packets pending dispatch to the Broker.
|
||||
The most important ordering rules are:
|
||||
|
@ -90,14 +90,13 @@ In this case, the proper way to disconnect would be to call [refmem mqtt_client
|
||||
);
|
||||
```
|
||||
|
||||
[section:reusing_the_client Restarting the Client after disconnection]
|
||||
[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.
|
||||
See [link async_mqtt5.getting_started.configuration Configuring Your MQTT Connection] for more information.
|
||||
|
||||
```
|
||||
int main() {
|
||||
|
@ -4,7 +4,7 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:asio_compliance Compliance with Boost.Asio]
|
||||
[section:asio_compliance Compliance With Boost.Asio]
|
||||
|
||||
Every asynchronous operation in __Asio__ has associated characteristics that specify their behaviour.
|
||||
|
||||
|
@ -4,13 +4,13 @@
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:multithreading Using the mqtt_client in a multithreaded environment]
|
||||
[section:multithreading Using the mqtt_client in a Multithreaded Environment]
|
||||
[nochunk]
|
||||
|
||||
This chapter provides information about thread safety of the __Client__ and other __Asio__-compliant objects
|
||||
and provides examples of how to write thread-safe code in multithreaded environments.
|
||||
|
||||
[section:thread_safety Thread safety of ASIO-compliant objects]
|
||||
[section:thread_safety Thread Safety of ASIO-Compliant Objects]
|
||||
|
||||
A common misconception exists regarding the "thread safety" of ASIO-compliant asynchronous objects,
|
||||
specifically around the belief that initialising such an object with a __STRAND__
|
||||
@ -37,7 +37,7 @@ Instead, it encourages developers to implement their own concurrency management
|
||||
|
||||
[endsect] [/thread_safety]
|
||||
|
||||
[section:executors_threads_strands Executors, threads, and strands]
|
||||
[section:executors_threads_strands Executors, Threads, and Strands]
|
||||
|
||||
Before delving into thread-safe programming, it is essential to understand the distinction between executors and threads.
|
||||
Executors are not threads but mechanisms for scheduling how and when work gets done.
|
||||
@ -56,7 +56,7 @@ Refer to __ASIO_STRANDS__ for more details.
|
||||
|
||||
[endsect] [/executors_threads_strands]
|
||||
|
||||
[section:thread_safe_code Writing thread-safe code]
|
||||
[section:thread_safe_code Writing Thread-Safe Code]
|
||||
|
||||
As mentioned previously, it is the user's responsibility to ensure that none of the __Client__'s member functions
|
||||
are called concurrently from separate threads.
|
||||
|
@ -8,25 +8,21 @@
|
||||
|
||||
[section:hello_world_over_tcp Hello World over TCP/IP]
|
||||
This example illustrates the process of setting up the Client to connect to the Broker via TCP/IP and publish a "Hello World!" message.
|
||||
[import ../../../example/hello_world_over_tcp.cpp]
|
||||
[hello_world_over_tcp]
|
||||
[endsect] [/hello_world_over_tcp]
|
||||
|
||||
[section:hello_world_over_tls Hello World over TLS/SSL]
|
||||
This example illustrates the process of setting up the Client to connect to the Broker via TLS/SSL and publish a "Hello World!" message.
|
||||
[import ../../../example/hello_world_over_tls.cpp]
|
||||
[hello_world_over_tls]
|
||||
[endsect] [/hello_world_over_tls]
|
||||
|
||||
[section:hello_world_over_websocket_tcp Hello World over Websocket/TCP]
|
||||
This example illustrates the process of setting up the Client to connect to the Broker via Websocket/TCP and publish a "Hello World!" message.
|
||||
[import ../../../example/hello_world_over_websocket_tcp.cpp]
|
||||
[hello_world_over_websocket_tcp]
|
||||
[endsect] [/hello_world_over_websocket_tcp]
|
||||
|
||||
[section:hello_world_over_websocket_tls Hello World over Websocket/TLS]
|
||||
This example illustrates the process of setting up the Client to connect to the Broker via Websocket/TLS and publish a "Hello World!" message.
|
||||
[import ../../../example/hello_world_over_websocket_tls.cpp]
|
||||
[hello_world_over_websocket_tls]
|
||||
[endsect] [/hello_world_over_websocket_tls]
|
||||
|
||||
@ -34,7 +30,6 @@ This example illustrates the process of setting up the Client to connect to the
|
||||
This example shows how to use __Client__ as a publisher that publishes sensor readings every `5` seconds.
|
||||
The __Client__ uses TCP to connect to the Broker and modified __USE_AWAITABLE__ as the completion token.
|
||||
|
||||
[import ../../../example/publisher.cpp]
|
||||
[publisher]
|
||||
[endsect]
|
||||
|
||||
@ -43,14 +38,12 @@ This example shows how to use __Client__ as a receiver.
|
||||
The __Client__ subscribes and indefinitely receives Application Messages from the Broker.
|
||||
The __Client__ uses TCP to connect to the Broker and modified __USE_AWAITABLE__ as the completion token.
|
||||
|
||||
[import ../../../example/receiver.cpp]
|
||||
[receiver]
|
||||
[endsect]
|
||||
|
||||
[section:multiflight_client The multiflight Client]
|
||||
This example shows how to use __Client__ to simultaneously dispatch multiple requests.
|
||||
|
||||
[import ../../../example/multiflight_client.cpp]
|
||||
[multiflight_client]
|
||||
[endsect]
|
||||
|
||||
@ -59,7 +52,6 @@ This example demonstrates how to use the __Client__ with its support for per-ope
|
||||
using parallel group.
|
||||
Specifically, in this example, the __Client__ will subscribe to a Topic and try to receive a message from the Topic within `5 seconds`.
|
||||
|
||||
[import ../../../example/timeout_with_parallel_group.cpp]
|
||||
[timeout_with_parallel_group]
|
||||
[endsect]
|
||||
|
||||
@ -69,21 +61,18 @@ using awaitable operators.
|
||||
Specifically, in this example, a call to [refmem mqtt_client async_publish] and [refmem mqtt_client async_disconnect] must complete
|
||||
within `5 seconds`. Otherwise, they will be cancelled.
|
||||
|
||||
[import ../../../example/timeout_with_awaitable_operators.cpp]
|
||||
[timeout_with_awaitable_operators]
|
||||
[endsect]
|
||||
|
||||
[section:hello_world_in_multithreaded_env Hello World in a multithreaded environment using callbacks]
|
||||
This example demonstrates how to publish a "Hello World" message in a multithreaded environment using callbacks (`post`/`dispatch`).
|
||||
|
||||
[import ../../../example/hello_world_in_multithreaded_env.cpp]
|
||||
[hello_world_in_multithreaded_env]
|
||||
[endsect]
|
||||
|
||||
[section:hello_world_in_coro_multithreaded_env Hello World in a multithreaded environment using coroutines]
|
||||
This example demonstrates how to publish a "Hello World" message in a multithreaded environment using coroutines (`co_spawn`).
|
||||
|
||||
[import ../../../example/hello_world_in_coro_multithreaded_env.cpp]
|
||||
[hello_world_in_coro_multithreaded_env]
|
||||
[endsect]
|
||||
|
||||
|
87
doc/qbk/reference/concepts/LoggerType.qbk
Normal file
87
doc/qbk/reference/concepts/LoggerType.qbk
Normal file
@ -0,0 +1,87 @@
|
||||
[/
|
||||
Copyright (c) 2023-2024 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:LoggerType LoggerType concept]
|
||||
|
||||
`LoggerType` represents an object type that will be used by the __Client__ to log events.
|
||||
|
||||
A type satisfies the `LoggerType` concept if it defines [*any number (including zero)] of the following functions:
|
||||
|
||||
[table:log_functions
|
||||
[[Function signature] [Arguments] [Description]]
|
||||
[
|
||||
[`void at_resolve(error_code ec, std::string_view host, std::string_view port, const asio::ip::tcp::resolver::results_type& eps);`]
|
||||
[
|
||||
[*`ec`] is the `error_code` returned by the resolve operation.
|
||||
|
||||
[*`host`] is the hostname used in the resolve.
|
||||
|
||||
[*`port`] is the port used in the resolve.
|
||||
|
||||
[*`eps`] is a list of endpoints returned by the resolve operation.
|
||||
]
|
||||
[Invoked when the resolve operation is complete.]
|
||||
]
|
||||
[
|
||||
[`void at_tcp_connect(error_code ec, asio::ip::tcp::endpoint ep);`]
|
||||
[
|
||||
[*`ec`] is the `error_code` returned by the TCP connect operation.
|
||||
|
||||
[*`ep`] is a TCP endpoint used to establish the TCP connection.
|
||||
]
|
||||
[Invoked when the TCP connect operation is complete.]
|
||||
]
|
||||
[
|
||||
[`void at_tls_handshake(error_code ec, asio::ip::tcp::endpoint ep);`]
|
||||
[
|
||||
[*`ec`] is the `error_code` returned by the the TLS handshake operation.
|
||||
|
||||
[*`ep`] is a TCP endpoint used to establish the TLS handshake.
|
||||
]
|
||||
[Invoked when the TLS handshake operation is complete.]
|
||||
]
|
||||
[
|
||||
[`void at_ws_handshake(error_code ec, asio::ip::tcp::endpoint ep);`]
|
||||
[
|
||||
[*`ec`] is the `error_code` returned by the the WebSocket handshake operation.
|
||||
|
||||
[*`ep`] is a TCP endpoint used to establish the WebSocket handshake.
|
||||
]
|
||||
[Invoked when the WebSocket handshake operation is complete.]
|
||||
]
|
||||
[
|
||||
[`void at_connack(reason_code rc, bool session_present, const connack_props& ca_props);`]
|
||||
[
|
||||
[*`rc`] is the `reason_code` received in the __CONNACK__ packet indicating the result of the MQTT handshake.
|
||||
|
||||
[*`session_present`] A flag indicating whether the Broker already has a session associated with this connection.
|
||||
|
||||
[*`ca_props`] __CONNACK_PROPS__ received in the __CONNACK__ packet.
|
||||
]
|
||||
[Invoked when the __CONNACK__ packet is received, marking the completion of the MQTT handshake. ]
|
||||
]
|
||||
[
|
||||
[`void at_disconnect(reason_code rc, const disconnect_props& dc_props);`]
|
||||
[
|
||||
[*`rc`] is the `reason_code` received in the __DISCONNECT__ packet specifying the reason behind the disconnection.
|
||||
|
||||
[*`dc_props`] __DISCONNECT_PROPS__ received in the __DISCONNECT__ packet.
|
||||
]
|
||||
[Invoked when the __DISCONNECT__ packet is received, indicating that the Broker wants to close this connection. ]
|
||||
]
|
||||
]
|
||||
|
||||
For example, a type `T` that defines `at_connack` and `at_disconnect` functions with their respective arguments is considered a valid `LoggerType`.
|
||||
This allows you to create your own `LoggerType` classes with functions of interest.
|
||||
|
||||
All defined functions are invoked directly within the __Client__ using its default executor.
|
||||
If the __Client__ is initialized with an explicit or implicit strand, none of the functions will be invoked concurrently.
|
||||
|
||||
[warning Defined functions should not block and stop the __Client__ from doing work. ]
|
||||
|
||||
A class that satifies this concept is [ghreflink include/async_mqtt5/logger.hpp logger].
|
||||
|
||||
[endsect]
|
@ -20,7 +20,6 @@
|
||||
<member><link linkend="async_mqtt5.ref.subscribe_options">subscribe_options</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.subscribe_topic">subscribe_topic</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.will">will</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.logger">logger</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
@ -42,7 +41,6 @@
|
||||
<member><link linkend="async_mqtt5.ref.disconnect_rc_e">disconnect_rc_e</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.qos_e">qos_e</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.retain_e">retain_e</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.log_level">log_level</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
@ -75,6 +73,12 @@
|
||||
<member><link linkend="async_mqtt5.ref.Reason_codes">Reason codes</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.Error_handling">Error handling</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Logging</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="async_mqtt5.ref.LoggerType">LoggerType</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.logger">logger</link></member>
|
||||
<member><link linkend="async_mqtt5.ref.log_level">log_level</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row></tbody>
|
||||
</tgroup>
|
||||
|
@ -31,6 +31,7 @@
|
||||
[include concepts/StreamType.qbk]
|
||||
[include concepts/TlsContext.qbk]
|
||||
[include concepts/is_authenticator.qbk]
|
||||
[include concepts/LoggerType.qbk]
|
||||
[include reason_codes/Reason_codes.qbk]
|
||||
[include properties/will_props.qbk]
|
||||
[include properties/connect_props.qbk]
|
||||
@ -1470,18 +1471,24 @@
|
||||
<xsl:when test="contains($qualified-name, 'StreamType')">StreamType</xsl:when>
|
||||
<xsl:when test="contains($qualified-name, 'TlsContext')">TlsContext</xsl:when>
|
||||
<xsl:when test="contains($qualified-name, 'is_authenticator')">is_authenticator</xsl:when>
|
||||
<xsl:when test="contains($qualified-name, 'LoggerType')">LoggerType</xsl:when>
|
||||
<xsl:otherwise></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:if test="string-length($template-type) > 0">
|
||||
<xsl:value-of select="substring-before($qualified-name, $template-type)"/>
|
||||
<xsl:text>__</xsl:text><xsl:value-of select="$template-type"/><xsl:text>__</xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($template-type) > 0">
|
||||
<xsl:value-of select="substring-before($qualified-name, $template-type)"/>
|
||||
<xsl:text>__</xsl:text><xsl:value-of select="$template-type"/><xsl:text>__</xsl:text>
|
||||
<xsl:value-of select="substring-after($qualified-name, $template-type)"/>
|
||||
<xsl:if test="count(declname) > 0">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$qualified-name"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="mqtt-ref-id">
|
||||
@ -1524,7 +1531,8 @@
|
||||
or contains(type, 'ExecutionContext')
|
||||
or contains(type, 'TlsContext')
|
||||
or contains(type, 'StreamType')
|
||||
or contains(type, 'is_authenticator')">
|
||||
or contains(type, 'is_authenticator')
|
||||
or contains(type, 'LoggerType')">
|
||||
<xsl:call-template name="mqtt-template">
|
||||
<xsl:with-param name="qualified-name" select="$type"/>
|
||||
</xsl:call-template>
|
||||
|
@ -15,23 +15,36 @@
|
||||
#include <async_mqtt5.hpp>
|
||||
|
||||
int main() {
|
||||
//[init_tcp_client
|
||||
// Initialize the execution context required to run I/O operations.
|
||||
boost::asio::io_context ioc;
|
||||
|
||||
// Construct the Client with ``__TCP_SOCKET__`` as the underlying stream.
|
||||
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
|
||||
//async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
|
||||
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket, std::monostate /* TlsContext */, async_mqtt5::logger> client(
|
||||
ioc, {} /* tls_context */, async_mqtt5::logger(async_mqtt5::log_level::debug)
|
||||
);
|
||||
//]
|
||||
|
||||
//[configure_tcp_client
|
||||
// 1883 is the default TCP MQTT port.
|
||||
client.brokers("broker.hivemq.com", 1883)
|
||||
.credentials("async_mqtt5_tester")
|
||||
.async_run(boost::asio::detached);
|
||||
//]
|
||||
|
||||
//[publish_hello_world
|
||||
client.async_publish<async_mqtt5::qos_e::at_most_once>(
|
||||
"async-mqtt5/test", "Hello world!",
|
||||
async_mqtt5::retain_e::yes, async_mqtt5::publish_props {},
|
||||
[&client](async_mqtt5::error_code ec) {
|
||||
std::cout << ec.message() << std::endl;
|
||||
|
||||
// Disconnnect the Client.
|
||||
client.async_disconnect(boost::asio::detached);
|
||||
}
|
||||
);
|
||||
//]
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
|
||||
write_prefix();
|
||||
std::clog
|
||||
<< "tls handshake: "
|
||||
<< "TLS handshake: "
|
||||
<< ep.address().to_string() << ":" << ep.port()
|
||||
<< " - " << ec.message()
|
||||
<< std::endl;
|
||||
@ -148,7 +148,7 @@ public:
|
||||
|
||||
write_prefix();
|
||||
std::clog
|
||||
<< "ws handshake: "
|
||||
<< "WebSocket handshake: "
|
||||
<< ep.address().to_string() << ":" << ep.port()
|
||||
<< " - " << ec.message()
|
||||
<< std::endl;
|
||||
|
@ -41,6 +41,7 @@ namespace asio = boost::asio;
|
||||
* the stream of bytes between the Client and the Broker. The transport must be
|
||||
* ordered and lossless.
|
||||
* \tparam \__TlsContext\__ Type of the context object used in TLS/SSL connections.
|
||||
* \tparam \__LoggerType\__ Type of object used to log events within the Client.
|
||||
*
|
||||
* \par Thread safety
|
||||
* ['Distinct objects]: safe. \n
|
||||
@ -85,7 +86,7 @@ public:
|
||||
*
|
||||
* \param ex An executor that will be associated with the Client.
|
||||
* \param tls_context A context object used in TLS/SSL connection.
|
||||
* \param logger An object used to log events within the Client.
|
||||
* \param logger An object satisfying the \__LoggerType\__ concept used to log events within the Client.
|
||||
*/
|
||||
explicit mqtt_client(
|
||||
const executor_type& ex,
|
||||
@ -102,7 +103,7 @@ public:
|
||||
* \tparam \__ExecutionContext\__ Type of a concrete execution context.
|
||||
* \param context Execution context whose executor will be associated with the Client.
|
||||
* \param tls_context A context object used in TLS/SSL connection.
|
||||
* \param logger An object used to log events within the Client.
|
||||
* \param logger An object satisfying the \__LoggerType\__ concept used to log events within the Client.
|
||||
*
|
||||
* \par Precondition
|
||||
* \code
|
||||
@ -442,7 +443,7 @@ public:
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
* equivalent to using \__ASYNC_IMMEDIATE\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation depends on the \ref qos_e specified:\n
|
||||
@ -535,7 +536,7 @@ public:
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
* equivalent to using \__ASYNC_IMMEDIATE\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
@ -608,7 +609,7 @@ public:
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
* equivalent to using \__ASYNC_IMMEDIATE\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
@ -677,7 +678,7 @@ public:
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
* equivalent to using \__ASYNC_IMMEDIATE\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
@ -745,7 +746,7 @@ public:
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
* equivalent to using \__ASYNC_IMMEDIATE\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
@ -871,8 +872,6 @@ public:
|
||||
* \param props An instance of \__DISCONNECT_PROPS\__.
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
@ -935,8 +934,6 @@ public:
|
||||
*
|
||||
* \param token Completion token that will be used to produce a
|
||||
* completion handler. The handler will be invoked when the operation completes.
|
||||
* On immediate completion, invocation of the handler will be performed in a manner
|
||||
* equivalent to using \__POST\__.
|
||||
*
|
||||
* \par Handler signature
|
||||
* The handler signature for this operation:
|
||||
|
@ -25,7 +25,14 @@ using error_code = boost::system::error_code;
|
||||
* such as the hostname, port, and path.
|
||||
*/
|
||||
struct authority_path {
|
||||
std::string host, port, path;
|
||||
/** The hostname of the authority as a domain name or an IP address. */
|
||||
std::string host;
|
||||
|
||||
/** The port number used for communication. */
|
||||
std::string port;
|
||||
|
||||
/** Specifies the endpoint path relevant to WebSocket connections. */
|
||||
std::string path;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -115,8 +115,8 @@ BOOST_AUTO_TEST_CASE(successful_connect_debug) {
|
||||
BOOST_TEST_MESSAGE(log);
|
||||
BOOST_TEST_WARN(contains(log, "resolve"));
|
||||
BOOST_TEST_WARN(contains(log, "connect"));
|
||||
BOOST_TEST_WARN(contains(log, "tls handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "ws handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "TLS handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
|
||||
BOOST_TEST_WARN(contains(log, "connack"));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user