【问题标题】:Timeout for boost::beast sync http clientboost::beast 同步 http 客户端超时
【发布时间】:2019-06-30 23:11:02
【问题描述】:

我正在从Boost Beast examples 改编synchronous HTTP client。不幸的是,示例客户端不包括超时选项,有时会卡在我的工作负载中。我尝试使用

添加超时
beast::get_lowest_layer(stream).expires_after(NetworkSettings::BASIC_TIMEOUT);

在调用写/读操作之前,但这些似乎只在使用 async_read/write 时起作用。 From what I found,似乎基本的 boost asio 仅支持异步操作的超时。所以我的问题是,野兽是否有能力在阻塞的连接/读/写调用上使用超时。

【问题讨论】:

  • 我没有 Beast 方面的经验,但是您是否尝试过使用 std::future 及其 wait_for 成员函数? asio 库(由 beast 包装)支持 use_future,它将阻塞行为模拟为同步客户端。

标签: c++ boost boost-asio boost-beast


【解决方案1】:

超时不适用于 Asio 中的同步 I/O。由于 Beast 是 asio 之上的一层,它也不支持同步 I/O 的超时。如果您想要超时,则必须使用异步 API。您可以使用堆栈式协程,或者如果您有足够现代的编译器,您可以尝试使用无堆栈式协程 (co_await)。这些允许您编写看似同步但使用异步接口的代码。

Beast 文档对此很清楚: “出于可移植性的原因,网络不为同步流操作提供超时或取消功能。”

https://www.boost.org/doc/libs/1_70_0/libs/beast/doc/html/beast/using_io/timeouts.html

如果您希望连接操作超时,请使用beast::tcp_stream 的实例并调用async_connect 成员函数: https://www.boost.org/doc/libs/1_70_0/libs/beast/doc/html/beast/using_io/timeouts.html#beast.using_io.timeouts.connecting

【讨论】:

  • 感谢您的澄清。那我就用异步操作吧。
【解决方案2】:

你可以使用这样的东西。

尝试将stream.connect(results)更改为

auto Future = stream.async_connect(endpoint, net::use_future);
if(Future.wait_for(std::chrono::seconds(1)) == std::future_status::timeout){

   std::cout<<"timed_out";
   ....
}else {

}

注意事项:

1)您可能需要以下头文件

#include<boost/asio/use_future.hpp>
#include<chrono>
#include<future>

2) 因为你是 asyc_* 发起的;你需要打电话给ioc.run();

3) 您需要另一个线程来执行ioc.run();,因为我们正在通过异步模拟同步——必须有人运行事件循环。

另一种方法:您可以使用其本机句柄显式设置套接字选项(我从未这样做过)。但在此之前,请阅读此答案https://stackoverflow.com/a/51850018/5198101

const int timeout = 200;
::setsockopt(socket.native_handle(), SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof timeout);//SO_SNDTIMEO for send ops

https://linux.die.net/man/7/socket

SO_RCVTIMEO 和 SO_SNDTIMEO 指定接收或发送超时 直到报错。参数是 struct timeval。如果 这段时间的输入或输出功能块,并且数据有 已发送或接收,该函数的返回值将是 传输的数据量;如果没有数据被传输并且 已达到超时,然后返回 -1,并将 errno 设置为 EAGAIN 或 EWOULDBLOCK 或 EINPROGRESS(用于 connect(2))就像套接字一样 被指定为非阻塞的。如果超时设置为零( 默认),那么操作将永远不会超时。超时只有 对执行套接字 I/O 的系统调用的影响(例如,read(2), recvmsg(2),发送(2),发送消息(2));超时对 select(2)、poll(2)、epoll_wait(2) 等等。

【讨论】:

  • 这会反驳首先使用异步 IO 的想法,对吧?
  • @sehe 嗯...肯定阻塞 IO 不是一件好事((在可扩展性的情况下),但看起来,OP 正在尝试同步客户端,所以我给出了解决方法。
  • @Explorer_N 是的,不需要期货或非便携式套接字选项,因为 Beast 提供了一个具有超时的异步连接功能(请参阅boost.org/doc/libs/1_70_0/libs/beast/doc/html/beast/using_io/…)我已经更新了我的答案以反映这一点。
  • @VinnieFalco,感谢您的回复,您知道,OP 知道 async_* 提供的超时操作,但他说他正在试验同步客户端,这意味着他想阻止直到 connect发生了,看起来sync connect 没有timeout,这就是我建议std::future 的原因...当然co_await 也可以,但最后,它只是另一个异步模型,如@987654336 @..关于setsockopt--我通过链接讨论可移植性的答案将其留给OP自行决定。你还觉得我的回答不对吗?
  • @VinnieFalco 而你认为std::future 不会做 OP 正在寻找的工作?
猜你喜欢
  • 2016-06-19
  • 2018-09-05
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2019-02-27
相关资源
最近更新 更多