async_recv() funtion
You need to call the async_recv() function when you want to receive MQTT packets. It is similar to Boost.Asio’s async_read()
function, allowing you to control packet receiving timing. async_mqtt
does not use handler registering style APIs such as set_publish_handler()
. If you need handler registering APIs, you can create them using async_recv()
.
The async_recv()
function is more flexible than handler registering APIs. Additionally, it works well with the Completion Token model.
packet_variant
async_recv()'s CompletionToken parameters are error_code and packet_variant.
If there is no error, you can access the pv
using the visit
function and overloaded lambda expressions. Each lambda expression corresponds to the actual packet type.
packet_variant
is a variant type of all MQTT packets and std::monostate
. std::monostate
is only used if error_conde is not success
.
Note
|
async_mqtt has basic_foobar type and foobar type if the type contains MQTT’s Packet Identifier. basic_foobar takes a PacketIdBytes parameter. basic_foobar<2> is the same as foobar . The MQTT spec defines the size of the Packet Identifier as 2. However, some clustering brokers use an expanded Packet Identifier for inter-broker communication. General users don’t need to worry about basic_foobar types; simply use foobar .
|
You can access packet_variant
as follows:
namespace am = async_mqtt; // always use this namespace alias in this document
// Let's say the completion token arguments are `error_code ec, packet_variant pv`.
if (ec) {
std::cout
<< "MQTT CONNACK recv error:"
<< ec.message()
<< std::endl;
}
else {
// `pv` can be converted to boolean. If `pv` contains a valid packet, it converts to `true`;
// otherwise (`std::monostate`) , it converts to `false`.
BOOST_ASSERT(pv); // if ec is not an error, then pv is always converted to true
pv.visit(
am::overload {
[&](am::v3_1_1::connack_packet const& p) {
std::cout
<< "MQTT CONNACK recv "
<< "sp:" << p.session_present()
<< std::endl;
},
// other packets handling code here
[](auto const&) {}
}
);
}
Control Packet Type filter
You might be interested in specific packets. Your application may not need to handle non-important packets like PINGRESP, PUBACK, PUBREC, PUBREL, and PUBCOMP packets.
You can filter packets as follows:
// ep is endpoint shared_ptr
ep->async_recv(am::filter::match, {am::control_packet_type::publish}, completion_token);
When you set filter::match
as the first argument, the second parameter is a list of matching MQTT Control Packet types. If unmatched packets are received, the completion_token
isn’t invoked, but the received packets are appropriately processed. If an error occurs, the completion_token
is invoked with a ec
that contains the error.
// ep is endpoint
ep->async_recv(am::filter::except, {am::control_packet_type::pingresp, am::control_packet_type::puback}, completion_token);
When you set filter::except
as the first argument, the second parameter is a list of MQTT Control Packet types to ignore. If the packets in the list are received, the completion_token
isn’t invoked, but the received packets are appropriately processed. If an error occurs, the completion_token
is invoked with a packet_variant
that contains the error.
async_send() function
MQTT has various packet types, such as CONNECT, PUBLISH, SUBSCRIBE, and so on. To send a packet, first create the packet and then pass it as a parameter to async_send()
. If the send timing is a protocol error, the async_send()
CompletionToken
is invoked with a system_error
.
You can call async_send()
continuously. The async_mqtt
endpoint has a queuing mechanism. When the previous async_send()
function’s CompletionToken
is invoked, the next packet in the queue is sent, if it exists.
Packet Based APIs
async_mqtt
automatically updates the endpoint’s internal state when sending and receiving packets. See Packet Based APIs.