使用 use_future 提升 Asio async_send_to 多播不起作用

Posted

技术标签:

【中文标题】使用 use_future 提升 Asio async_send_to 多播不起作用【英文标题】:Boost Asio async_send_to multicast with use_future does not work 【发布时间】:2020-09-25 09:08:14 【问题描述】:

ITNOA

我有一个程序想要将一条带有 async_send_to 的消息发送到一个多播组。但我想这个动作是阻塞而不是异步的,所以我使用 use_future 来实现这个目标,如下所示

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

我像下面这样使用这个类

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;

我的问题是为什么send message 永远不会在我的控制台中写入?

奇怪的是,我用tcpdump -i eth0 -nnSX port 8765 检查我的网络,在调用async_send_to 后,我可以看到发送到网络的多播消息,但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

【问题讨论】:

【参考方案1】:

io_context::run 在没有待执行的作业时返回。

您可以创建 work guard 以确保即使没有启动异步任务也不会完成运行。使用make_work_guard函数:

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

【讨论】:

这是不可能的,因为你可以看到发送方法被阻塞result.get()所以如果我想在发送方法之后启动io_context::run,我不能这样做,因为发送方法最终不会返回 更新答案。 感谢您的回答,我还有一个问题,我可以在另一个线程或 std::async 上运行 message_sender.send 吗?当我做这样的事情时,我得到了异常std::future_error: No associated state 我添加了一些关于***.com/q/64063109/1539100的另一个问题,请看,谢谢:) @sorosh_sabz 我添加了该问题的答案。

以上是关于使用 use_future 提升 Asio async_send_to 多播不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 asio 提升线程池:线程随机不执行

使用 Qt 提升 asio

提升 Asio 和 OpenSSL 1.1.0

提升 asio async_read_some 超时

提升asio断网处理

内存 SPIKE - 提升 ASIO 异步读取