Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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


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

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

Ответ 2

Я использовал asio docs, чтобы создать это:

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);

Я отлаживал его, и он, похоже, делает то, что он должен.