boost :: beast同步HTTP客户端超时

时间:2019-06-30 23:11:02

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

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

beast::get_lowest_layer(stream).expires_after(NetworkSettings::BASIC_TIMEOUT);

在调用写/读操作之前,但似乎仅在使用async_read / write时起作用。 From what I found,看来基本的boost asio仅支持异步操作超时。因此,我的问题是,野兽是否具有在阻止连接/读取/写入呼叫时使用超时的功能。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:-1)

您可以使用类似这样的东西。

尝试将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();,因为我们正在通过异步进行同步模拟-有人必须运行事件循环。

另一种方法:您可以使用其本机句柄(我从未做过)显式设置socket选项。但在这样做之前,请先阅读此答案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。如果   在这段时间内输入或输出功能块,并且数据具有   发送或接收时,该函数的返回值为   传输的数据量;如果没有数据传输并且   达到超时,然后将errno设置为EAGAIN并返回-1   或EWOULDBLOCK或EINPROGRESS(用于connect(2)),就像套接字   被指定为非阻塞。如果超时设置为零(   默认值),则操作将永不超时。超时只有   对于执行套接字I / O的系统调用(例如read(2),   recvmsg(2),send(2),sendmsg(2));超时对没有影响   select(2),poll(2),epoll_wait(2)等。