Boost Asio async_recieve_from multicast con use_future no funciona simultáneamente con async_send_to
ITNOA
Quiero escribir un programa que envíe y reciba multidifusión simultáneamente como a continuación
int main()
{
const string group_address = "235.127.1.1";
constexpr uint16_t PORT_NUMBER = 8765;
boost::asio::io_context io_context;
auto work_guard = boost::asio::make_work_guard(io_context);
BoostMessageSender message_sender(group_address, "eth1", PORT_NUMBER, io_context);
BoostMessageReceiver message_receiver(group_address, "eth1", PORT_NUMBER, io_context);
std::thread t1([&io_context]()
{
cout << __LINE__ << endl;
io_context.run();
});
this_thread::sleep_for(1s);
std::array<char, 20> data = {};
auto result = std::async(std::launch::async, [&message_receiver, &data]()
{
message_receiver.receive(gw::buffer(data));
cout << " receive finished" << endl; // does not reach this line :(((
});
this_thread::sleep_for(1s);
message_sender.send("Any body there!");
result.wait(); // Raise exception what(): std::future_error: No associated state
cout << "receive message: ";
std::copy(std::begin(data),
std::end(data),
std::ostream_iterator<char>(std::cout, ""));
io_context.stop();
t1.join();
return 0;
}
Mi problema es ¿por qué result.wait () causa para generar una excepción?
La nota quizás importante es que cuando elimino la message_sender.sendlínea, este programa no genera ninguna excepción y línea de result.wait()bloque hasta el final. pero cuando se message_sender.sendagrega la línea , este programa genera una excepción y no funciona correctamente.
Mi message_sender es igual a este código.
Y mi message_receiver es como abajo
BoostMessageReceiver::BoostMessageReceiver(const std::string& group_address, const std::string& interface_name, uint16_t port_number, ba::io_context& io_context)
: AbstractMessageReceiver(group_address, interface_name, port_number)
, io_context(io_context)
, listen_endpoint(ba::ip::address_v4::any(), port_number)
, socket(io_context)
{
socket.open(listen_endpoint.protocol());
socket.set_option(ba::ip::udp::socket::reuse_address(true));
socket.bind(listen_endpoint);
// Join to multicast group
socket.set_option(ba::ip::multicast::enable_loopback(true));
socket.set_option(ba::ip::multicast::join_group(ba::ip::address::from_string(group_address)));
}
std::pair<bool, std::size_t> BoostMessageReceiver::receive(const AbstractMessageReceiver::MutableBuffer& buffer) noexcept
{
ba::ip::udp::endpoint sender_endpoint;
std::future<std::size_t> result = socket.async_receive_from(ba::buffer(buffer.data(), buffer.size()), sender_endpoint, ba::use_future);
return std::make_pair(result.get() != 0, result.get());
}
¿Dónde está mi error?
Pruebo estos códigos en las siguientes plataformas
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
Respuestas
Que está recibiendo no_stateporque getel futurepuede ser llamado una sola vez.
Abajo
std::make_pair(result.get() != 0, result.get());
get se llama dos veces.
Ver referencia :
Notas Se recomienda a las implementaciones que detecten el caso cuando valid () sea falso antes de la llamada y arrojen un std :: future_error con una condición de error de std :: future_errc :: no_state.
Después de la primera llamada de get, validvuelve false.