关闭后连接成功

单线程应用程序。

它不会每次都发生,只有1.5小时的高负荷。

  • TCP ::插座:: async_connect
  • tcp :: socket :: close(by deadline_timer)
  • async_connect_handler提供了成功的error_code(百万次之一),但socket由(2)关闭。 99.999%的时间使得errno = 125(ECANCELED)。
  • 有没有可能是套接字实现或boost asio以某种方式执行此操作:

  • async_connect
  • 异步成功发布到io_service
  • 靠计时器关闭
  • 异步成功由我处理,不受关闭影响
  • 现在通过在我的变量中保存状态解决问题,忽略接受成功。

    Linux 2.6(Fedora)。 升压1.46.0

    PS:对我来说可能存在的错误......但如果不是这样的话,可以平稳地运行几天。


    正如伊戈尔在评论中提到的,完成处理程序已经排队。

    这种情况是执行操作和调用处理程序之间的时间分离的结果。 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提供了一些处理超时的例子。


    我接受twsansbury的回答,只是想添加更多信息。

    关于shutdown():

    void async_recv_handler( boost::system::error_code ec_recv, std::size_t count )
    {
        if ( !m_socket.is_open() )
            return; // first time don't trust to ec_recv
        if ( ec_recv )
        {
            // oops, we have error
            // log
            // close
            return;
        }
        // seems that we are just fine, no error in ec_recv, we can gracefully shutdown the connection
        // but shutdown may fail! this check is working for me
        boost::system::error_code ec_shutdown;
        // second time don't trusting to ec_recv
        m_socket.shutdown( t, ec_shutdown );
        if ( !ec_shutdown )
            return;
        // this error code is expected
        if ( ec_shutdown == boost::asio::error::not_connected )
           return;
        // other error codes are unexpected for me
        // log << ec_shutdown.message()
        throw boost::system::system_error(ec_shutdown);
    }
    
    链接地址: http://www.djcxy.com/p/62675.html

    上一篇: connect success after close

    下一篇: boost::asio socket sharing across threads in the HTTP Server 3 example