首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >任何boost::asio异步调用是否自动超时?

任何boost::asio异步调用是否自动超时?
EN

Stack Overflow用户
提问于 2011-02-08 02:57:51
回答 2查看 8.8K关注 0票数 20

我有一个客户端和服务器异步使用boost::asio。我想添加一些超时来关闭连接,并可能在出现错误时重试。

我最初的想法是,每当我调用async_函数时,我都应该启动一个deadline_timer,让它在我期望异步操作完成后过期。现在我在想,这是否在每种情况下都是严格必要的。

例如:

  • async_resolve可能使用内置了超时的系统解析器(例如,resolv.h中的RES_TIMEOUT可能会被/etc/resolv.conf中的配置覆盖)。通过添加我自己的计时器,我可能会与用户希望他的解析器工作的方式发生冲突。it
  • etc.

中内置了

  • For async_connectconnect(2)系统调用的某种超时

那么,哪些(如果有的话) async_调用可以保证在“合理”的时间范围内调用它们的处理程序呢?如果操作可以超时,是否会向处理程序传递basic_errors::timed_out错误或其他信息?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-09 13:27:27

所以我做了一些测试。根据我的结果,很明显它们依赖于底层的操作系统实现。作为参考,我用一个常用的Fedora内核进行了测试:2.6.35.10-74.fc14.x86_64

底线是,async_resolve()看起来是唯一一种不需要设置deadline_timer就可以使用的情况。实际上,在其他任何情况下,合理的行为都需要它。

async_resolve()

async_resolve()的调用导致4个查询相隔5秒。处理程序在请求后20秒被调用,错误为boost::asio::error::host_not_found

我的解析程序默认的超时时间为2次尝试,超时时间为5秒(resolv.h),因此它发送的查询数似乎是配置的两倍。可以通过在/etc/resolv.conf中设置options timeoutoptions attempts来修改该行为。在每种情况下,无论attempts设置为多少,发送的查询数都是两倍,之后会使用host_not_found错误调用处理程序。

在测试中,单个配置的名称服务器是黑洞路由的。

async_connect()

使用黑洞路由的目的地调用async_connect()会导致在大约189秒后调用处理程序,并显示错误boost::asio::error::timed_out

堆栈发送了初始SYN和5次重试。3秒后发送第一次重试,每次重试超时加倍(3+6+12+24+48+96=189)。重试次数可以更改:

代码语言:javascript
复制
% sysctl net.ipv4.tcp_syn_retries
net.ipv4.tcp_syn_retries = 5

选择默认值5以符合RFC 1122 (4.2.3.5):

必须将SYN段的重传计时器设置得足够大,以提供该段至少3分钟的重传。当然,应用程序可以更快地关闭连接(即放弃打开连接的尝试)。

3分钟= 180秒,尽管RFC似乎没有指定上限。没有什么能阻止实现永远重试。

async_write()

只要套接字的发送缓冲区未满,就会立即调用此处理程序。

我的测试建立了一个TCP连接,并设置了一个计时器,使其在一分钟后调用async_write()。在建立连接的那一分钟内,但在async_write()调用之前,我尝试了各种混乱:

将下游路由器设置为在下游防火墙中对destination.

  • Clearing会话的后续流量设置黑洞,以便它将使用来自destination.

  • Unplugging my Ethernet

  • Running /etc/init.d/network stop

的欺骗RST进行回复,从而实现

无论我做了什么,下一个async_write()都会立即调用它的处理程序来报告成功。

在防火墙欺骗RST的情况下,连接立即关闭,但我无法知道这一点,直到我尝试下一个操作(它将立即报告boost::asio::error::connection_reset)。在其他情况下,连接将保持打开状态,并且不会向我报告错误,直到17-18分钟后最终超时。

对于async_write()来说,最糟糕的情况是主机正在重新传输,并且发送缓冲区已满。如果缓冲区已满,async_write()将不会调用其处理程序,直到重新传输超时。Linux默认为15次重传:

代码语言:javascript
复制
% sysctl net.ipv4.tcp_retries2
net.ipv4.tcp_retries2 = 15

每次重新传输后,重新传输之间的时间都会增加(并且基于许多因素,例如特定连接的估计往返时间),但限制在2分钟。因此,对于默认的15次重传和最坏情况下的2分钟超时,调用async_write()处理程序的上限是30分钟。当调用它时,error被设置为boost::asio::error::timed_out

async_read()

只要建立了连接并且没有接收到数据,就不应该调用它的处理程序。我还没来得及测试它。

票数 34
EN

Stack Overflow用户

发布于 2011-02-08 03:07:37

这两个调用可能会有超时,但在这两个超时之前的时间长度可能会让您感到困扰。(我知道,在终止进程之前,我已经让一个连接处于静止状态,并尝试使用boost::asio在单个连接呼叫上连接超过10分钟)。此外,async_readasync_write调用没有与之关联的超时,因此,如果您希望在读取和写入时设置超时,您仍然需要一个deadline_timer

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4925253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档