The MQTT protocol requires the underlying transport protocol that ensures orderly, lossless transmission of byte streams between the Client and Server in both directions.
The following examples demonstrate how to establish a network connection using suitable transport protocols such as TCP/IP, TLS/SSL, and WebSocket.
To create a TCP/IP connection with a Broker, initialise
with mqtt_client
boost::asio::ip::tcp::socket
as the StreamType
.
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <async_mqtt5.hpp>
void tcp_setup() {
boost::asio::io_context ioc;
// Use boost::asio::ip::tcp::socket
as the underlying stream.
async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket> client(ioc);
}
To establish a secure and encrypted connection using the TLS/SSL protocol,
supply a context object that meets the TlsContext
requirements. Additionally, initialise
with an underlying
stream that implements TLS/SSL protocol as the mqtt_client
StreamType
.
This example will demonstrate how to set up an SSL connection using boost::asio::ssl::context
and boost::asio::ssl::stream<
.
To use SSL support in Boost.Asio,
OpenSSL is required.
boost::asio::ip::tcp::socket
>
#include <boost/asio/io_context.hpp> #include <boost/asio/ssl.hpp> #include <boost/asio/ip/tcp.hpp> #include <async_mqtt5.hpp> // External customization point. namespace async_mqtt5 { template <typename StreamBase> struct tls_handshake_type<asio::ssl::stream<StreamBase>> { static constexpr auto client = asio::ssl::stream_base::client; static constexpr auto server = asio::ssl::stream_base::server; }; // This client uses this funcction to indicate which hostname it is // attempting to connect to at the start of the handshaking process. template <typename StreamBase> void assign_tls_sni( const authority_path& ap, boost::asio::ssl::context& ctx, boost::asio::ssl::stream<StreamBase>& stream ) { SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str()); } } // end namespace async_mqtt5 // The certificate file in PEM format. constexpr char certificate[] = "-----BEGIN CERTIFICATE-----\n" "...........................\n" "-----END CERTIFICATE-----\n" ; void ssl_setup() { boost::asio::io_context ioc; // Context satisfyingTlsContext
requirements that the underlying SSL stream will use. // The purpose of the context is to allow us to set up TLS/SSL-related options. // SeeSSL
for more information and options. boost::asio::ssl::context context(boost::asio::ssl::context::tls_client); async_mqtt5::error_code ec; // Add the trusted certificate authority for performing verification. context.add_certificate_authority(boost::asio::buffer(certificate), ec); // Set peer verification mode used by the context. // This will verify that the server's certificate is valid and signed by a trusted certificate authority. context.set_verify_mode(boost::asio::ssl::verify_peer, ec); // Useboost::asio::ssl::stream<
as theboost::asio::ip::tcp::socket
>StreamType
withboost::asio::ssl::context
as theTlsContext
. async_mqtt5::mqtt_client< boost::asio::ssl::stream<boost::asio::ip::tcp::socket>, boost::asio::ssl::context > client(ioc, std::move(context)); }
The WebSocket connection can be established over an unencrypted TCP/IP connection or an encrypted TLS/SSL connection.
The following example will showcase setting up WebSocket over TCP/IP and
WebSocket over TLS/SLL connection using boost::beast::websocket::stream<NextLayer>
.
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/websocket.hpp>
#include <async_mqtt5.hpp>
void websocket_tcp_setup() {
boost::asio::io_context ioc;
// Use boost::beast::websocket::stream<boost::asio::ip::tcp::socket
>
as the underlying stream.
async_mqtt5::mqtt_client<
boost::beast::websocket::stream<boost::asio::ip::tcp::socket>
> client(ioc);
}
#include <boost/asio/io_context.hpp> #include <boost/asio/ssl.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/beast/websocket.hpp> #include <async_mqtt5.hpp> constexpr char ca[] = "-----BEGIN CERTIFICATE-----\n" "...........................\n" "-----END CERTIFICATE-----\n" ; namespace boost::beast::websocket { //boost::beast::boost::beast::websocket::async_teardown
is a free function // designed to initiate the asynchronous teardown of a connection. // The specific behaviour of this function is based on the NextLayer type (Socket type) used to create theboost::beast::websocket::stream<NextLayer>
. // Boost.Beast library includes an implementation of this function forboost::asio::ip::tcp::socket
. // However, the callers are responsible for providing a suitable overload of this function for any other type, // such asboost::asio::ssl::stream<
as shown in this example. template <typename TeardownHandler> void async_teardown( boost::beast::role_type role, asio::ssl::stream<asio::ip::tcp::socket>& stream, TeardownHandler&& handler ) { return stream.async_shutdown(std::forward<TeardownHandler>(handler)); } } // end namespace boost::beast::websocket namespace async_mqtt5 { template <typename StreamBase> struct tls_handshake_type<asio::ssl::stream<StreamBase>> { static constexpr auto client = asio::ssl::stream_base::client; static constexpr auto server = asio::ssl::stream_base::server; }; template <typename streambase> void assign_tls_sni( const authority_path& ap, asio::ssl::context& ctx, asio::ssl::stream<streambase>& stream ) { ssl_set_tlsext_host_name(stream.native_handle(), ap.host.c_str()); } } // end namespace async_mqtt5 void websocket_tls_setup() { boost::asio::io_context ioc; boost::asio::ssl::context context(boost::asio::ssl::context::tls_client); async_mqtt5::error_code ec; context.add_certificate_authority(boost::asio::buffer(ca), ec); context.set_verify_mode(boost::asio::ssl::verify_peer, ec); async_mqtt5::mqtt_client< boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>, boost::asio::ssl::context > client(ioc, std::move(context)); }boost::asio::ip::tcp::socket
>
Once the
has been initialised
with a suitable mqtt_client
StreamType
,
it is prepared for configuration and utilisation.