Boost Asio async_recieve_from 与 use_future 的多播不能与 async_send_to 同时工作
Boost Asio async_recieve_from multicast with use_future does not work simultaneously with async_send_to
ITNOA
我想像下面这样编写同时发送和接收多播的程序
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;
}
我的问题是为什么 result.wait() 导致引发异常?
可能重要的一点是,当我删除 message_sender.send
行时,该程序不会引发任何异常,并且 result.wait()
行会阻塞直到结束。但是当添加 message_sender.send
行时,该程序引发异常并且无法正常工作。
我的message_sender等于代码。
我的message_receiver如下
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());
}
我哪里错了?
我在以下平台上测试了这些代码
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
您得到 no_state
因为 get
on future
只能被调用一次。
低于
std::make_pair(result.get() != 0, result.get());
get
被调用了两次。
参见reference:
Notes The implementations are encouraged to detect the case when
valid() is false before the call and throw a std::future_error with an
error condition of std::future_errc::no_state.
第一次调用 get
后,valid
returns false
.
ITNOA
我想像下面这样编写同时发送和接收多播的程序
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;
}
我的问题是为什么 result.wait() 导致引发异常?
可能重要的一点是,当我删除 message_sender.send
行时,该程序不会引发任何异常,并且 result.wait()
行会阻塞直到结束。但是当添加 message_sender.send
行时,该程序引发异常并且无法正常工作。
我的message_sender等于
我的message_receiver如下
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());
}
我哪里错了?
我在以下平台上测试了这些代码
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
您得到 no_state
因为 get
on future
只能被调用一次。
低于
std::make_pair(result.get() != 0, result.get());
get
被调用了两次。
参见reference:
Notes The implementations are encouraged to detect the case when valid() is false before the call and throw a std::future_error with an error condition of std::future_errc::no_state.
第一次调用 get
后,valid
returns false
.