Обратите внимание: используется платформа 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.
Почему таймаут иногда не работает?
time()
имеет точность в секундах, поэтому он не будет очень точным для кода синхронизации. Вместо этого используйтеGetTickCount/64()
илиQueryPerformanceCounter()
. - person Remy Lebeau   schedule 15.05.2019recv()
мог заблокироваться навсегда, когда действует небесконечный тайм-аутSO_RCVTIMEO
. Значит, происходит что-то еще. Кроме того, просто к вашему сведению, еще один способ реализовать тайм-аут чтения — вызватьselect()
перед вызовомrecv()
. - person Remy Lebeau   schedule 15.05.2019OVERLAPPED
? - person Drake Wu   schedule 16.05.2019