【问题标题】:boost::asio cancel or close doesn't work on async_handleboost::asio 取消或关闭在 async_handle 上不起作用
【发布时间】:2018-09-12 08:06:42
【问题描述】:

boost::asio::ip::udp:socket 不能cancel() async_handle,也不能close()。

这是测试程序:

{
    boost::asio::io_context io_core;
    boost::asio::ip::udp::socket udp_socket1(io_core, udp::v4());
    char buff[200];
    boost::asio::ip::udp::endpoint endpoint1(boost::asio::ip::address::from_string("127.0.0.1"), 9999);

    cout << udp_socket1.is_open() << endl;
    udp_socket1.async_send_to(boost::asio::buffer(buff, 200), endpoint1, [&udp_socket1](const boost::system::error_code& ec, size_t wlen) {
        cout << udp_socket1.is_open() << endl;
        //assert(0);
    });
    cout << udp_socket1.is_open() << endl;
    udp_socket1.close();
    udp_socket1.async_send_to(boost::asio::buffer(buff, 200), endpoint1, [&udp_socket1](const boost::system::error_code& ec, size_t wlen) {
        cout << udp_socket1.is_open() << endl;
        //assert(0);
    });
    cout << udp_socket1.is_open() << endl;

    udp_socket1.close();
    io_core.run();
    system("pause");
}

使用 boost 1.67.0、WIN10、vs2017 BOOST_ASIO_DISABLE_IOCP 和 BOOST_ASIO_CANCELIO 根据documentation定义

我是不是没抓住重点?

如果我是正确的,如何解决这个问题?

【问题讨论】:

    标签: c++ c++11 boost udp boost-asio


    【解决方案1】:

    异步操作不会立即完成。您的代码看起来像您期望的那样。

    将您的代码简化为:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <iostream>
    
    using boost::asio::ip::udp;
    
    int main() {
        std::cout << std::boolalpha;
    
        boost::asio::io_context io;
        boost::asio::ip::udp::socket s {io, udp::v4()};
        boost::asio::ip::udp::endpoint const ep {{}, 9999};
    
        auto trace = [&s](char const* caption) { std::cout << caption << s.is_open() << std::endl; };
        auto handler = [=](boost::system::error_code, size_t) { trace("handler: "); };
    
        trace("main #1: ");
    
        char buff[200] = {};
        s.async_send_to(boost::asio::buffer(buff), ep, handler);
    
        trace("main #2: ");
        s.close();
    
        s.async_send_to(boost::asio::buffer(buff), ep, handler);
    
        trace("main #3: ");
        s.close();
    
        io.run();
    }
    

    处理程序只在io.run() 之后运行是有道理的;显然,套接字在第一次关闭之前只是“打开”的:

    main #1: true
    main #2: true
    main #3: false
    handler: false
    handler: false
    

    这完全符合预期。所以,要么你应该处理错误:

    Live On Coliru

    auto trace = [&s](char const* caption) { std::cout << caption << (s.is_open()?"open":"closed") << std::endl; };
    auto handler = [=](boost::system::error_code ec, size_t) { 
        trace(("handler(" + ec.message() + "): ").c_str()); 
    };
    

    改为打印:

    main #1: open
    main #2: open
    main #3: closed
    handler(Success): closed
    handler(Bad file descriptor): closed
    

    注意,也许令人惊讶的是,第一次发送操作仍然成功。与我的预期相反,这表明发送实际上是在 async_send_to 调用时启动的,但完成延迟到 io.run() 之后(仍然显示套接字已关闭)。

    也许你根本不想要异步操作:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <iostream>
    
    using boost::asio::ip::udp;
    
    int main() {
        std::cout << std::boolalpha;
    
        boost::asio::io_context io;
        boost::asio::ip::udp::socket s {io, udp::v4()};
        boost::asio::ip::udp::endpoint const ep {{}, 9999};
    
        auto trace = [&s](char const* caption) { std::cout << caption << s.is_open() << std::endl; };
    
        trace("main #1: ");
    
        char buff[200] = {};
        try {
            /*size_t wlen =*/ s.send_to(boost::asio::buffer(buff), ep);
            trace("sent #1: ");
        } catch(boost::system::system_error const& e) {
            std::cout << "Send #1 failed: " << e.code().message() << std::endl;
        }
    
        trace("main #2: ");
        s.close();
    
        try {
            /*size_t wlen =*/ s.send_to(boost::asio::buffer(buff), ep);
            trace("sent #2: ");
        } catch(boost::system::system_error const& e) {
            std::cout << "Send #2 failed: " << e.code().message() << std::endl;
        }
    
        trace("main #3: ");
        s.close();
    
        io.run();
    }
    

    打印

    main #1: true
    sent #1: true
    main #2: true
    Send #2 failed: Bad file descriptor
    main #3: false
    

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2014-06-01
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      相关资源
      最近更新 更多