У меня есть следующий бит кода ASIO, который синхронно читает пакеты UDP. Проблема в том, что если в данный промежуток времени (30 секунд) не поступили пакеты данных заданного размера, я бы хотел, чтобы функция recieve_from возвращала с какой-то ошибкой, чтобы указать время ожидания.
for (;;)
{
boost::array<char, 1000> recv_buf;
udp::endpoint remote_endpoint;
asio::error_code error;
socket.receive_from(asio::buffer(recv_buf), // <-- require timeout
remote_endpoint, 0, error);
if (error && error != asio::error::message_size)
throw asio::system_error(error);
std::string message = make_daytime_string();
asio::error_code ignored_error;
socket.send_to(asio::buffer(message),
remote_endpoint, 0, ignored_error);
}
Если посмотреть на документацию, то не для вызовов, ориентированных на UDP, поддерживается механизм тайм-аута.
Как правильно (также, если возможно, переносимо) использовать тайм-аут с синхронными вызовами UDP в ASIO?
Насколько я знаю, это невозможно. Запустив синхронный receive_from
вы заблокировали выполнение кода системным вызовом recvmsg
от #include <sys/socket.h>
,
Что касается переносимости, я не могу говорить за Windows, но решение на основе Linux с BSD будет выглядеть так:
void SignalHandler(int signal) {
// do what you need to do, possibly informing about timeout and calling exit()
}
...
struct sigaction signal_action;
signal_action.sa_flags = 0;
sigemptyset(&signal_action.sa_mask);
signal_action.sa_handler = SignalHandler;
if (sigaction(SIGALRM, &signal_action, NULL) == -1) {
// handle error
}
...
int timeout_in_seconds = 5;
alarm(timeout_in_seconds);
...
socket.receive_from(asio::buffer(recv_buf), remote_endpoint, 0, error);
...
alarm(0);
Если это вообще невозможно, я бы порекомендовал перейти на полную асинхронность и запустить ее в boost::asio::io_service
,
Других решений пока нет …