2

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

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

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

4

2 回答 2

3

超时不适用于 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

于 2019-07-04T03:49:21.517 回答
-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();

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

另一种方法:您可以使用其本机句柄显式设置套接字选项(我从未这样做过)。但在此之前,请阅读此答案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)、send(2)、sendmsg(2));超时对 select(2)、poll(2)、epoll_wait(2) 等无效。

于 2019-07-02T07:42:55.403 回答