I have program that want to send a message with async_send_to to one multicast group. but I want to this action is blocking not async, so I use use_future for achieve this goal like below
gw::BoostMessageSender::BoostMessageSender(const std::string& group_address, const std::string& interface_name, uint16_t port_number, ba::io_context& io_context)
: AbstractMessageSender(group_address, interface_name, port_number)
, io_context(io_context)
, endpoint(ba::ip::address::from_string(group_address), port_number)
, socket(io_context, endpoint.protocol())
{
if (!socket.is_open())
socket.open(endpoint.protocol());
socket.set_option(ba::ip::udp::socket::reuse_address(true));
}
bool gw::BoostMessageSender::send(const std::string& message) noexcept
{
std::future<std::size_t> result = socket.async_send_to(ba::buffer(message), endpoint, ba::use_future);
return result.get() == message.size();
}
And I use this class like below
int main()
{
const string group_address = "235.127.1.1";
constexpr uint16_t PORT_NUMBER = 8765;
boost::asio::io_context io_context;
BoostMessageSender message_sender(group_address, "eth1", PORT_NUMBER, io_context);
std::thread t1([&io_context]()
{
io_context.run();
});
this_thread::sleep_for(1s);
message_sender.send("Any bodey there?");
cout << "send message: "; // --- this line is not run never :(((
io_context.stop();
t1.join();
return 0;
}
My problem is why send message
does not write in my console never?
Stranger that is, I check my network with tcpdump -i eth0 -nnSX port 8765
and after call async_send_to
I can see multicast message that sent to network, but result.get()
never return result and hung on that.
Where is my wrong?
I test these code on below platforms
Visual Studio 2019 16.7.4
Windows 10 1909 latest update
Boost 1.73.0
Ubuntu 20.04.1 LTS
GCC 9.3.0
Boost 1.71.0
io_context::run
returns when there is no pending jobs to be executed.
You can create work guard to ensure that run doesn't finish even if no async tasks were initiated. Use make_work_guard
function:
boost::asio::io_context io_context;
auto workGuard = boost::asio::make_work_guard(io_context);