2010-01-05 18 views
5

Sto eseguendo il porting di un'applicazione di rete Windows su linux e ho dovuto affrontare un problema di timeout con select call su linux. I seguenti blocchi funzione per l'intero valore di timeout e ritorni mentre ho controllato con uno sniffer di pacchetti che il client ha già inviato i dati.Socket select() funziona in Windows e timeout in 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); 
} 

risposta

12

penso che il primo parametro da select() dovrebbe essere socket+1.

Dovresti davvero usare un altro nome come socket anche per altre cose. Solitamente viene utilizzato sock.

+0

@jamessan Ah, sì mi ha fatto sì che;) – epatel

+0

Sì, grazie, che ha risolto il mio problema. –

+0

Giusto. 'int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout);' dove nfds è 'il descrittore di file con il numero più alto in uno qualsiasi dei tre set, più 1'. – jamessan

2

Dalla pagina man di selezionare:

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

descrittori sono controllati in ogni set I primi NFDS; cioè, i descrittori da 0 a nfds-1 nei set di descrittori sono esaminati.

Così il primo parametro per selezionare dovrebbe essere presa + 1.

return select(socket + 1, &fds, 0, 0, &timeout); 
1

Il primo parametro a select (...) è il numero di descrittore di file per verificare nel set. La tua chiamata sta dicendo di guardare solo il descrittore di file 0, che non è quasi certamente quello che è stato impostato su socket.

2

select in Windows ignora il primo parametro. Da MSDN:

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

Parameters 

nfds [in] 

    Ignored. The nfds parameter is included only for 
    compatibility with Berkeley sockets. 
...
2

Il problema è che il fd_set in Linux è una matrice di bit (in origine era solo un int, ma poi si poteva guardare solo i primi 16 io del del vostro processo). In windows fd_set c'è una serie di socket con una lunghezza in primo piano (motivo per cui Windows non ha bisogno di sapere quanti bit guardare).

La funzione sondaggio() accetta una serie di record da guardare su Linux e ha altri vantaggi che lo rendono una scelta migliore di select().

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

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

    return poll(& sockpoll, 1, msec) ; 
} 
+0

Grazie per l'informazione, è questa funzione di poll() la piattaforma incrociata per caso? –

+0

Hmm, su Linux vuoi davvero usare epoll, preferibilmente in modalità edge-triggered. –

Problemi correlati