Boost Asio async_send_to multicast com use_future não funciona

Sep 25 2020

ITNOA

Eu tenho um programa que deseja enviar uma mensagem com async_send_to para um grupo multicast. mas eu quero que esta ação seja de bloqueio não assíncrono, então eu uso use_future para atingir este objetivo como abaixo

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();
}

E eu uso essa classe como abaixo

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;
}

Meu problema é por send messageque não escrevo no meu console nunca?

Estranho isto é, eu verifico minha rede com tcpdump -i eth0 -nnSX port 8765e após a chamada async_send_toposso ver a mensagem multicast que foi enviada para a rede, mas result.get()nunca retorno resultado e penduro nisso.

Onde está o meu erro?

Eu testo esse código nas plataformas abaixo

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

Respostas

rafix07 Sep 25 2020 at 17:00

io_context::run retorna quando não há trabalhos pendentes a serem executados.

Você pode criar proteção de trabalho para garantir que a execução não termine, mesmo que nenhuma tarefa assíncrona tenha sido iniciada. make_work_guardFunção de uso :

boost::asio::io_context io_context;
auto workGuard = boost::asio::make_work_guard(io_context);