C++ Boost ASIO: как читать / писать с таймаутом?

Из чтения других записей переполнения стека и boost::asio документация, я подтвердил, что нет синхронных вызовов чтения / записи ASIO, которые также предоставляют простой в использовании тайм-аут в качестве параметра для вызова.

Я нахожусь в процессе преобразования приложения сокетов старой школы Linux с вызовами select(2), которые используют тайм-ауты, и мне нужно сделать более или менее то же самое.

Так что это лучший способ сделать это в boost::asio? Глядя на документацию asio, можно найти много запутанных примеров различных вещей, связанных с таймерами, но я совершенно запутался.

Я хотел бы видеть простой для чтения пример этого: чтение из сокета, но ожидание в течение максимум X секунд, после чего функция либо возвращается ни с чем, либо возвращается с тем, что она смогла прочитать из сокета до истечения времени ожидания.

2 ответа

Решение

Это было упомянуто в списках рассылки asio, также есть билет, запрашивающий эту функцию. Подводя итог, предлагается использовать асинхронные методы, если вы хотите тайм-ауты и отменяемость.


Если вы не можете преобразовать в асинхронные методы, вы можете попробовать SO_RCVTIMEO а также SO_SNDTIMEO варианты сокетов. Они могут быть установлены с setsockoptдескриптор можно получить с помощью метода boost::asio::ip::tcp::socket::native. man 7 socket на странице руководства написано

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

Я использовал несколько документов asio для создания этого:

class TimeoutAdjust
{
public:
  TimeoutAdjust(unsigned int dwTimeout) : m_dwTimeout(dwTimeout) {};

  template<class Protocol>
  int level(const Protocol& p) const {return SOL_SOCKET;}

  template<class Protocol>
  int name(const Protocol& p) const {return SO_SNDTIMEO;}

  template<class Protocol>
  const void* data(const Protocol& p) const {return &m_dwTimeout;}

  template<class Protocol>
  size_t size(const Protocol& p) const {return sizeof(m_dwTimeout);}
private:
  unsigned int m_dwTimeout;
};

Использование:

TimeoutAdjust adjust(5000);
sSocket.set_option(adjust);

Я отладил его, и он, кажется, делает то, что должен.

Другие вопросы по тегам