单线程应用程序。
它不会每次都发生,只有在高负载1.5小时后才会发生。
套接字实现或boost asio是否可能以某种方式做到这一点:
现在,通过将状态保存在变量中来解决问题,而忽略接受成功。
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_wait
和handle_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/