关闭后连接成功
单线程应用程序。
它不会每次都发生,只有1.5小时的高负荷。
有没有可能是套接字实现或boost asio以某种方式执行此操作:
现在通过在我的变量中保存状态解决问题,忽略接受成功。
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_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提供了一些处理超时的例子。
我接受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