问题描述
单线程应用程序。
它每次发生不中,只有1.5小时后,高负荷的。
It happens not every time, only after 1.5 hours of high load.
- TCP套接字:: :: async_connect
- TCP套接字:: ::接近(由deadline_timer)
- async_connect_handler给成功错误_ code(一百万次的),但插座是由(2)关闭。时间的99.999%,它给了错误号= 125(ECANCELED)。
难道套接字实现或推动ASIO莫名其妙地做到这一点:
Is it possible that socket implementation or boost asio somehow do this:
- async_connect
- 发布异步成功io_service对象
- 附近计时器
- 异步的成功,不会受关闭
由我处理
现在,在我的变量节能状态,忽略接受成功解决了。
Right now solved by saving state in my variables, ignoring accept success.
的Linux 2.6(Fedora的)。
升压1.46.0
Linux 2.6 (fedora).Boost 1.46.0
PS:ofcouse在我的部分可能的错误......但流畅运行数天如果没有这个
PS: ofcouse possible bug on my part... But runs smoothly for days if not this.
推荐答案
由于伊戈尔在评论中提到,在完成处理程序已经排队。
As Igor mentions in the comments, the completion handler is already queued.
此情况是当一个操作执行并且当被调用的处理程序之间的时间分离的结果。对文档的, <$c$c>io_service::run_one(), <$c$c>io_service::poll(),和<$c$c>io_service::poll_one()特定于提及的处理程序,而不是操作。在该方案中,插座:: async_connect()
运行和 deadline_timer :: async_wait()
操作完成在相同事件循环迭代。这将导致两个处理程序被添加到 io_service对象
延期调用,在未指定的顺序。
This scenario is the result of a separation in time between when an operation executes and when a handler is invoked. The documentation for io_service::run()
, io_service::run_one()
, io_service::poll()
, and io_service::poll_one()
is specific to mention handlers, and not operations. In the scenario, the socket::async_connect()
operation and deadline_timer::async_wait()
operation complete in the same event loop iteration. This results in both handlers being added to the io_service
for deferred invocation, in an unspecified order.
考虑下面的代码片段,突出的情景:
Consider the following snippet that accentuates the scenario:
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()
被调用,无论插座:: async_connect()
和 deadline_timer :: async_wait()
操作可能已完成,引起 handle_wait
和 handle_connect
要准备好调用从内部 io_service对象
在未指定的顺序。要妥善处理好这一未指定的顺序,额外的逻辑需要从内部发生 handle_wait()
和 handle_connect()
查询当前状态,并确定其他处理程序被调用,而不是仅仅在状态(错误_ code
)的操作依据。
When io_service_.run_one()
is invoked, both socket::async_connect()
and deadline_timer::async_wait()
operations may have completed, causing handle_wait
and handle_connect
to be ready for invocation from within the io_service
in an unspecified order. To properly handle this unspecified order, additional logic need to occur from within handle_wait()
and handle_connect()
to query the current state, and determine if the other handler has been invoked, rather than depending solely on the status (error_code
) of the operation.
以确定其他处理程序调用了最简单的方法是:
The easiest way to determine if the other handler has invoked is:
- 在
handle_connect()
,检查插座仍然通过<$c$c>is_open().如果套接字仍然是开放的,那么handle_timer()
尚未调用。一个干净的方式来指示handle_timer()
的handle_connect()
已然是更新到期时间。 - 在
handle_timer()
,检查是否到期时间已经过去了。如果这是真的,那么handle_connect()
并没有跑,所以关闭套接字。
- In
handle_connect()
, check if the socket is still open viais_open()
. If the socket is still open, thenhandle_timer()
has not been invoked. A clean way to indicate tohandle_timer()
thathandle_connect()
has ran is to update the expiry time. - In
handle_timer()
, check if the expiry time has passed. If this is true, thenhandle_connect()
has not ran, so close the socket.
由此产生的处理程序可能如下所示:
The resulting handlers could look like the following:
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的提供了一些处理超时。
这篇关于提振收盘后ASIO async_connect成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!