таймаут для блокировки сокета TCP не работает - PullRequest
0 голосов
/ 15 мая 2019

Обратите внимание: платформа Windows , а не Linux.

У меня есть блокировка TCP-клиентского сокета. После подключения к удаленному серверу я установил тайм-аут чтения (так как удаленный сервер нестабилен, состояние сети плохое), а затем получил данные.

Иногда функция recv() никогда не возвращается, и моя программа не работает.

Код выглядит так:

// set timeout
{
    int millisec = 1000;
    if(setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (char*)&millisec, sizeof(int))) {
        MessageBox(0, "setsockopt fail", "", 0);
    }
}

unsigned begin_t = time(0);
int r = recv(sock_, ptr, static_cast<int>(size), 0);
unsigned end_t = time(0);

if(end_t - begin_t > 2) {
    MessageBox(0, "over 2 sec", "", 0); // This MessageBox popups some time
}

Я установил таймаут сокета на 1 секунду перед функцией recv(). Теоретически, recv() никогда не займет больше 1 секунды. Но иногда это занимает более 3 секунд, затем появляется MessageBox.

Почему время ожидания иногда не работает?

1 Ответ

1 голос
/ 16 мая 2019

SO_RCVTIMEO не поддерживается в сокете блокировки.

Если время ожидания блокирующего вызова истекло, соединение находится в неопределенное состояние и должно быть закрыто. Если сокет создан используя функцию WSASocket, тогда параметр dwFlags должен иметь Атрибут WSA_FLAG_OVERLAPPED, установленный для тайм-аута для работы должным образом. В противном случае таймаут никогда не вступит в силу.

Использование WSASocket с WSA_FLAG_OVERLAPPED. Или socket() (по умолчанию для режима WSA_FLAG_OVERLAPPED)

...