c++ - 关闭后 boost asio async_connect成功

标签 c++ sockets boost boost-asio

单线程应用程序。

它不会每次都发生,只有在高负载1.5小时后才会发生。

  • tcp::socket::async_connect
  • tcp::socket::close(截止截止时间)
  • async_connect_handler给出成功error_code(一百万次),但是套接字被(2)关闭。 99.999%的时间它给出errno = 125(已取消)。

  • 套接字实现或boost asio是否可能以某种方式做到这一点:
  • async_connect
  • 异步成功发布到io_service
  • 由计时器关闭
  • 由我处理的异步成功,不受
  • 的关闭影响

    现在,通过将状态保存在变量中来解决问题,而忽略接受成功。

    Linux 2.6(fedora)。
    boost 1.46.0

    PS:ofcouse可能是我的问题……但如果不是这样,则可以顺利运行数天。

    最佳答案

    正如Igor在评论中提到的那样,完成处理程序已经排队。

    这种情况是操作执行与调用处理程序之间时间间隔分开的结果。 io_service::run() io_service::run_one() io_service::poll() io_service::poll_one() 的文档专用于提及处理程序,而不是操作。在这种情况下,socket::async_connect()操作和deadline_timer::async_wait()操作在同一事件循环迭代中完成。这导致两个处理程序都以未指定的顺序添加到io_service中以进行延迟的调用。

    考虑以下突出场景的代码段:

    void handle_wait(const boost::system::error_code& error)
    {
      if (error) return;
      socket_.close();
    }
    
    timer_.expires_from_now(boost::posix_time::seconds(30));
    timer_.async_wait(&handle_wait);
    socket_.async_connect(endpoint_, handle_connect);
    boost::this_thread::sleep(boost::posix_time::seconds(60));
    io_service_.run_one();
    

    调用io_service_.run_one()时,socket::async_connect()deadline_timer::async_wait()操作可能都已完成,导致handle_waithandle_connect准备好以未指定的顺序从io_service内部调用。为了正确处理此未指定的顺序,需要在handle_wait()handle_connect()中发生附加逻辑以查询当前状态,并确定是否已调用其他处理程序,而不是仅取决于操作的状态(error_code)。

    确定其他处理程序是否已调用的最简单方法是:
  • handle_connect()中,检查套接字是否仍通过 is_open() 打开。如果套接字仍处于打开状态,则尚未调用handle_timer()。向handle_timer()指示handle_connect()已经运行的一种干净方法是更新到期时间。
  • handle_timer()中,检查是否已过期。如果是这样,则handle_connect()尚未运行,因此请关闭套接字。

  • 结果处理程序如下所示:
    void handle_wait(const boost::system::error_code& error)
    {
      // On error, return early.
      if (error) return;
    
      // If the timer expires in the future, then connect handler must have
      // first.
      if (timer_.expires_at() > deadline_timer::traits_type::now()) return;
    
      // Timeout has occurred, so close the socket.
      socket_.close();
    }
    
    void handle_connect(const boost::system::error_code& error)
    {
      // The async_connect() function automatically opens the socket at the start
      // of the asynchronous operation. If the socket is closed at this time then
      // the timeout handler must have run first.
      if (!socket_.is_open()) return;
    
      // On error, return early.
      if (error) return;
    
      // Otherwise, a connection has been established.  Update the timer state
      // so that the timeout handler does not close the socket.
      timer_.expires_at(boost::posix_time::pos_infin);
    }
    

    Boost.Asio提供了一些examples来处理超时。

    关于c++ - 关闭后 boost asio async_connect成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14586695/

    相关文章:

    ios - 从 IOS + Swift 将图像上传到 Socket.io 中的服务器

    c++ - Boost序列化子类

    c++ - "boost::mpl::identity<T>::type"在这里有什么意义?

    c++ - 在子类中设置变量

    C++将wchar_t反斜杠插入字符串

    c++ - 以 root ubuntu 身份自动运行我的可执行文件

    c++ - 我可以使用 Boost.Spirit 进行多功能数学 (AST) 模式匹配和操作吗?

    c++ - union 体的活跃成员,统一的初始化和构造函数

    c++ - 关于 boost::shared_ptr 赋值的问题(相对于 reset() 函数)

    具有多个接口(interface)的系统上的 Ruby 套接字绑定(bind)