boost :: asio отменить или закрыть не работает на async_handle - PullRequest
0 голосов
/ 12 сентября 2018

boost :: asio :: ip :: udp: сокет не может ни отменить () дескриптор async_handle, ни закрыть ().

Это тестовая программа:

{
    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");
}

с бустом 1.67.0, WIN10, vs2017 BOOST_ASIO_DISABLE_IOCP и BOOST_ASIO_CANCELIO определены в соответствии с документацией

Неужели я не смог получить точку?

Если я прав, как решить эту проблему?

1 Ответ

0 голосов
/ 12 сентября 2018

Асинхронные операции не завершаются немедленно.Ваш код выглядит так, как вы ожидаете.

Упрощение кода до:

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
...