2010-11-12 12 views
7

Nel client, ho unPerché questo server che ho scritto non rileva che il client ha chiuso il socket?

close(sockfd) 

dove sockfd è la presa che è collegato al server. Nel server ho questo:

if (sockfd.revents & POLLERR || 
    desc_set[i].revents & POLLHUP || desc_set[i].revents & POLLNVAL) { 
    close(sockfd.fd); 
    printf("Goodbye (connection closed)\n"); 
} 

Dove sockfd è un pollfd struct, e sockfd.fd è il descrittore di file della presa del cliente.

Quando il client chiude il socket come ho messo lì, il server non sembra rilevare con il secondo codice (desc_set [i] .revents & POLLHUP, etc.).

Qualcuno sa qual è il problema?

risposta

9

Sembra che tu sia riuscito a connettersi dal lato client a half close. In questo stato, la connessione può ancora inviare dati in una direzione, cioè funziona in modalità half-duplex. Questo è di progettazione e consentirebbe al tuo server di completare la risposta a qualunque cosa il client abbia inviato. In genere ciò significa completare un trasferimento di file e chiamare close() o rispondere a tutti gli aspetti della query. Nello stato semichiuso è ancora possibile inviare dati sensibilmente sul lato che ha già chiamato close(). Nel tuo server vedrai eof se si tenta di leggere però. close() significa solo "Ho finito di inviare, finire qualunque cosa ho chiesto".

POLLHUP, POLLERR e POLLNVAL controlla solo il lato di uscita della connessione locale, che è ancora valido qui. C'è uno POLLRDHUP, che è un'estensione GNU che dovrebbe rilevare l'altro lato di chiusura, ma i test che stai facendo sono solo controllando se è ancora scrivibile, non se è ancora leggibile.

Vedere anche this question, che sta parlando di Java, ma ancora molto correlato.

+0

Ci scusiamo per aver fatto una domanda simile a un principiante, ma come includere l'estensione GNU nel mio codice? – dasen

+0

#define _GNU_SOURCE prima di qualsiasi #include lo farà. Rendere la chiamata del server close() del proprio libero arbitrio una volta che è stata soddisfatta la richiesta è un modo molto, molto più carino. – Flexo

+0

Ho usato quell'estensione GNU, ma non si chiude ancora sul lato server. – dasen

4

Una chiusura remota o uno spegnimento di uscita non è né un errore né un blocco o uno stato non valido. È un evento di lettura tale che read() restituirà zero. Gestiscilo come parte della normale elaborazione di lettura.

BTW le condizioni di test riportate sopra devono leggere sockfd.revents & (POLLERR | POLLHUP | POLLNVAL).

+0

A destra - un grazioso 'close()' è segnalato da 'read()' restituisce 0, quindi è segnalato da 'POLLIN'. – caf

Problemi correlati