Как я могу попытаться считать данные с сокета с тайм-аутом? Я знаю, выбор, pselect, опрос, имеет поле тайм-аута, но использование их отключает "tcp быстрый путь" в tcp reno стек.
Единственная идея, которую я имею, состоит в том, чтобы использовать recv (fd..., MESSAGE_DONTWAIT) в цикле
Вы можете использовать функцию setsockopt , чтобы установить тайм-аут для операций приема:
SO_RCVTIMEO
Устанавливает значение тайм-аута, которое указывает максимальное количество времени на ввод функция ожидает завершения. Это принимает временную структуру с количество секунд и микросекунд указание предела продолжительности дождитесь операции ввода, чтобы полный. Если операция приема имеет заблокирован на это время без получив дополнительные данные, он должен возврат с частичным подсчетом или ошибкой установите на [EAGAIN] или [EWOULDBLOCK], если нет данные получены. По умолчанию для этого параметр равен нулю, что означает, что операция получения не должна истекать по тайм-ауту. Эта опция имеет временную структуру. Обратите внимание, что не все реализации разрешить установку этой опции.
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
Сообщается, что в Windows это должно быть сделано до вызова bind
. Я экспериментально подтвердил, что это можно сделать до или после bind
в Linux и OS X.
Установите обработчик для SIGALRM
, затем используйте alarm()
или ualarm()
перед обычным блокирующим recv()
. Если сигнал тревоги сработает, recv()
вернет ошибку с errno
, установленным в EINTR
.