单线程应用程序。
不是每次都发生,只有在高负荷1.5小时后才会发生。
套接字实现或提升asio是否可能以某种方式执行此操作:
现在通过在变量中保存状态来解决,忽略接受成功。
Linux 2.6(fedora)。 提升1.46.0
PS:对我而言可能存在错误...但如果不是这样的话,可以顺利运行几天。
答案 0 :(得分:4)
正如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
内调用{1}}以未指定的顺序排列。要正确处理此未指定的顺序,需要在handle_wait()
和handle_connect()
内进行额外的逻辑以查询当前状态,并确定是否已调用其他处理程序,而不是仅仅依赖于状态({ {1}})操作。
确定其他处理程序是否已被调用的最简单方法是:
error_code
中,通过is_open()
检查套接字是否仍处于打开状态。如果套接字仍处于打开状态,则尚未调用handle_connect()
。向handle_timer()
表明handle_timer()
已运行的干净方法是更新到期时间。handle_connect()
中,检查过期时间是否已过。如果这是真的,那么handle_timer()
没有运行,所以关闭套接字。生成的处理程序可能如下所示:
handle_connect()
Boost.Asio为处理超时提供了一些examples。
答案 1 :(得分:0)
我接受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);
}