Socket select () работает в Windows и время ожидания в Linux - PullRequest
5 голосов
/ 05 января 2010

Я портирую сетевое приложение Windows на Linux и столкнулся с проблемой тайм-аута при вызове select в Linux. Следующие функциональные блоки для всего значения времени ожидания и возвращаются, пока я проверял анализатор пакетов, что клиент уже отправил данные.

int recvTimeOutTCP( SOCKET socket, long sec, long usec )
{
  struct timeval timeout;
  fd_set fds;.

  timeout.tv_sec = sec;
  timeout.tv_usec = usec;
  FD_ZERO( &fds );
  FD_SET( socket, &fds );

  // Possible return values:
  // -1: error occurred
  // 0: timed out
  // > 0: data ready to be read
  cerr << "Waiting on fd " << socket << endl;
  return select(1, &fds, 0, 0, &timeout);
}

Ответы [ 5 ]

12 голосов
/ 05 января 2010

Я думаю, что первый параметр для select() должен быть socket+1.

Вы действительно должны использовать другое имя, поскольку socket также используется для других целей.Обычно используется sock.

2 голосов
/ 05 января 2010

Проблема в том, что fd_set в linux является битовым массивом (изначально это был просто int, но тогда вы могли наблюдать только первые 16 io вашего процесса). В windows fd_set представляет собой массив сокетов с длиной спереди (поэтому окнам не нужно знать, сколько бит смотреть).

Функция poll () принимает массив записей для просмотра в linux и имеет другие преимущества, которые делают ее лучшим выбором, чем select ().

int recvTimeOutTCP( SOCKET socket, long msec )
{
    int iret ;
    struct polldf   sockpoll ;

    sockpoll.fd= socket ;
    sockpoll.events= POLLIN ;

    return poll(& sockpoll, 1, msec) ;
}   
2 голосов
/ 05 января 2010

select в Windows игнорирует первый параметр. Из MSDN:

<code>C++
int select(
  __in     int nfds,
  __inout  fd_set *readfds,
  __inout  fd_set *writefds,
  __inout  fd_set *exceptfds,
  __in     const struct timeval *timeout
);</code>

Parameters

nfds [in]

    Ignored. The nfds parameter is included only for
    compatibility with Berkeley sockets.
...
2 голосов
/ 05 января 2010

На странице справки выберите:

int select(int nfds,
           fd_set* restrict readfds,
           fd_set* restrict writefds,
           fd_set* restrict errorfds, 
           struct timeval* restrict timeout);

Первые дескрипторы nfds проверяются в каждом наборе; то есть рассматриваются дескрипторы от 0 до nfds-1 в наборах дескрипторов.

Таким образом, первый параметр для выбора должен быть socket + 1.

return select(socket + 1, &fds, 0, 0, &timeout);
1 голос
/ 05 января 2010

Первый параметр select (...) - номер дескриптора файла, который нужно проверить в наборе. Ваш вызов говорит, чтобы он смотрел только на файловый дескриптор 0, который почти наверняка не то, что socket установлено в.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...