Тайм-аут для повышения :: Beast Sync HTTP-клиент - PullRequest
1 голос
/ 01 июля 2019

Я адаптирую синхронный HTTP-клиент из примеров Boost Beast .К сожалению, пример клиента не включает параметры времени ожидания и иногда застревает в моих рабочих нагрузках.Я пытался добавить таймауты с

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

перед вызовом операций записи / чтения, но, похоже, они работают только при использовании async_read / write. Из того, что я обнаружил , похоже, что базовый boost asio поддерживает тайм-ауты только для асинхронных операций.Поэтому у меня вопрос, есть ли у beast какие-либо возможности использовать тайм-аут при блокировке вызовов connect / read / write.

Ответы [ 2 ]

1 голос
/ 04 июля 2019

Тайм-ауты недоступны для синхронного ввода-вывода в Asio.Поскольку Beast является слоем выше asio, он также не поддерживает тайм-ауты для синхронного ввода-вывода.Если вы хотите тайм-ауты, вы должны использовать асинхронные 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

0 голосов
/ 02 июля 2019

Вы можете использовать что-то вроде этого.

попробуйте изменить 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 Укажите таймауты приема или отправки до сообщения об ошибке. Аргумент является структурой timeval. Если функциональные блоки ввода или вывода за этот период времени, и данные имеют отправлено или получено, возвращаемое значение этой функции будет количество переданных данных; если данные не были переданы и тайм-аут достигнут, то -1 возвращается с errno, установленным в EAGAIN или EWOULDBLOCK, или EINPROGRESS (для connect (2)), как если бы сокет был указан, чтобы быть неблокирующим. Если время ожидания установлено на ноль ( по умолчанию), то операция никогда не прекратится. Тайм-ауты есть только эффект для системных вызовов, которые выполняют сокет ввода / вывода (например, read (2), recvmsg (2), send (2), sendmsg (2)); таймауты не влияют на select (2), poll (2), epoll_wait (2) и т. д.

...