Установка тайм-аута для функции recv
Я читаю из сокета с помощью
3 ответов
вы должны проверить возвращаемое значение select
. select
вернутся 0
в случае истечения тайм-аута, поэтому вы должны проверить ошибку и вызвать recv
только если select
возвращается положительное значение:
при успешном выполнении select () и pselect() возвращают количество файловых дескрипторов, содержащихся в трех возвращаемых наборах дескрипторов (то есть общее количество битов, установленных в readfds, writefds, exceptfds), которое может быть равно нулю, если тайм-аут истекает до того, как что-либо интересное происходит.
int rv = select(s + 1, &set, NULL, NULL, &timeout);
if (rv == SOCKET_ERROR)
{
// select error...
}
else if (rv == 0)
{
// timeout, socket does not have anything to read
}
else
{
// socket has something to read
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == SOCKET_ERROR)
{
// read failed...
}
else if (recv_size == 0)
{
// peer disconnected...
}
else
{
// read successful...
}
}
другой способ установить тайм-аут на без использования select()
использовать setsockopt()
для установки сокета SO_RCVTIMEO
опция (на платформах, которые ее поддерживают).
в Windows код будет выглядеть следующим образом:
DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//...
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAETIMEDOUT)
//...
}
на других платформах, код будет выглядеть следующим образом:
struct timeval timeout;
timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
timeout.tv_usec = 0;
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
//...
recv_size = recv(s, rx_tmp, bufSize, 0);
if (recv_size == -1)
{
if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
//...
}
используйте макрос FD_ISSET (), чтобы проверить, есть ли данные для чтения. Если он возвращает false, не выполняйте чтение.