boost:: asio cancel или close не работает на асинхронном дескрипторе
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");
}
С boost 1.67.0, WIN10, vs2017 BOOST_ASIO_DISABLE_IOCP и BOOST_ASIO_CANCELIO, определенными в соответствии с документацией
Неужели я не понял сути?
Если я прав, как исправить эту проблему ?
1 ответ:
Асинхронные операции выполняются не сразу. Ваш код выглядит так, как вы ожидаете от них.
Упрощение кода до:
#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
Именно этого и следовало ожидать. Итак, либо вы должны обрабатывать ошибки:
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()
(сокет все еще показан уже закрытым).А может быть, вы вообще не хотели асинхронных операций:
#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