Mi chiedo cosa si dovrebbe fare quando il sondaggio imposta questi bit? Chiudere la presa, ignorarla o cosa?Come gestire il socket di Linux revents POLLERR, POLLHUP e POLLNVAL?
risposta
A POLLHUP
significa che la presa non è più collegata. In TCP, questo significa che FIN è stata ricevuta e inviata.
A POLLERR
significa che il socket ha ricevuto un errore asincrono. In TCP, questo in genere significa che è stato ricevuto o inviato un RST. Se il descrittore di file non è un socket, POLLERR
potrebbe indicare che il dispositivo non supporta il polling.
Per entrambe le condizioni precedenti, il descrittore del file socket è ancora aperto e non è stato ancora chiuso (ma è possibile che sia già stato chiamato shutdown()
). Un close()
sul descrittore di file rilascerà le risorse che sono ancora riservate per conto del socket. In teoria, dovrebbe essere possibile riutilizzare immediatamente la presa (ad es. Con un'altra chiamata connect()
).
A POLLNVAL
indica che il descrittore del file socket non è aperto. Sarebbe un errore a close()
esso.
Dipende dalla natura esatta dell'errore. Utilizzare getsockopt() per visualizzare il problema:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Valori: http://www.xinotes.net/notes/note/1793/
Il modo più semplice è quello di presumere che la presa non più utilizzabile in ogni caso è e chiuderlo.
Per me, stavo ricevendo POLLERR ma ... non avevo modo di scoprire quale fosse l'errore! Questa risposta sembra la migliore perché risponde alla domanda più generale di "best practice" per la gestione di POLLERR per la programmazione di rete. –
Non penso che funzioni nel caso generale. Almeno, Linux non documenta che può essere usato in questo modo. 'SO_ERROR' è documentato per restituire lo stato di errore del socket, ma il suo utilizzo per rilevare lo stato di errore del socket è descritto solo per la chiamata' connect() 'e non per altri. – jxh
POLLNVAL
significa che il valore del descrittore di file non è valido. Solitamente indica un errore nel tuo programma, ma puoi fare affidamento su restituendo POLLNVAL
se hai chiuso un descrittore di file e non hai aperto alcun file da quel momento che potrebbe aver riutilizzato il descrittore.
POLLERR
è simile agli eventi di errore da select
. Indica che una chiamata read
o write
restituirebbe una condizione di errore (ad esempio, errore I/O). Questo non include i dati fuori banda che inviano i segnali select
tramite la sua maschera errorfds
ma i segnali poll
tramite POLLPRI
.
POLLHUP
significa fondamentalmente che ciò che è all'altro capo della connessione ha chiuso la sua estremità della connessione. POSIX lo descrive come
Il dispositivo è stato disconnesso. Questo evento e POLLOUT si escludono a vicenda; uno stream non può mai essere scritto se si verifica un hangup.
Questo è abbastanza evidente per un terminale: il terminale è scomparso (stesso evento che genera un SIGHUP: la sessione modem è stato terminato, la finestra di terminale è stato chiuso, ecc). POLLHUP
non viene mai inviato per un file normale. Per tubi e prese, it depends on the operating system. Linux imposta POLLHUP
quando il programma sull'estremità di scrittura di un tubo chiude il tubo e imposta POLLIN|POLLHUP
quando l'altra estremità di un socket chiude il socket, ma POLLIN
solo per un arresto del socket. Recenti * BSD ha impostato POLLIN|POLLUP
quando la fine della scrittura di un pipe chiude la pipe e il comportamento per i socket è più variabile.
esempio FIFO minimo
Una volta capito quando queste condizioni si verificano, dovrebbe essere facile sapere cosa fare con loro.
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
compilazione con:
gcc -o poll.out -std=c99 poll.c
utilizzati:
sudo mknod -m 666 poll0.tmp p
./poll.out
In un'altra shell:
printf a >poll0.tmp
POLLHUP
Se non si modifica la fonte: ./poll.out
uscite:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Quindi:
POLLIN
accade quando l'ingresso diventa disponibilePOLLHUP
accade quando il file viene chiuso dallaprintf
close(pfd.fd);
epfd.fd *= -1;
ripulire le cose e smettiamo di riceverePOLLHUP
poll
pende sempre
Questa è l'operazione normale.
Ora è possibile ripristinare il FIFO per attendere il successivo open
oppure uscire dal ciclo se si è terminato.
POLLNAL
Se si commento fuori pfd.fd *= -1;
: ./poll.out
stampe:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
e loop per sempre.
Quindi:
POLLIN
ePOLLHUP
eclose
successo come prima- dato che non abbiamo impostato
pfd.fd
ad un numero negativo,poll
continua a cercare di utilizzare ilfd
che abbiamo chiuso - questo mantiene restituendo
POLLNVAL
per sempre
Quindi vediamo che questo non dovrebbe essere successo e indica un bug nel codice.
POLLERR
non so come generare un POLLERR
con FIFO. Fammi sapere se c'è un modo. Ma dovrebbe essere possibile con file_operations
di un driver di periferica.
Testato in Ubuntu 14.04.
- 1. Perché questo server che ho scritto non rileva che il client ha chiuso il socket?
- 2. implementazione di sondaggi su linux e implementazione sondaggio su solaris
- 3. Porting Winsock su socket Linux
- 4. prestazioni Socket su Linux
- 5. Come gestire il socket si disconnette in Dart?
- 6. Differenze su Java Socket tra Windows e Linux - Come gestirli?
- 7. Come posso "interconnettere" due socket in Linux?
- 8. Come visualizzare/modificare il timeout della connessione socket su Linux?
- 9. Timeout socket in C++ Linux
- 10. Linux, socket, connessione non bloccante
- 11. Invio di immagini tramite socket C++ (Linux)
- 12. Come funziona un buffer di socket Linux in overflow?
- 13. Come gestire le dipendenze Linux/Python?
- 14. La creazione di un nuovo thread Descrittori di file duplicati e descrittori di socket in Linux?
- 15. Il modo migliore per gestire snippet di codice in Linux?
- 16. Socket select() funziona in Windows e timeout in Linux
- 17. Come trovare la dimensione del buffer del socket di linux
- 18. Come gestire OpenSSL SSL_ERROR_WANT_READ/WANT_WRITE su socket non bloccanti
- 19. Come viene collegato un errore dal socket asincrono?
- 20. Problemi con SO_BINDTODEVICE opzione socket Linux
- 21. Chatroom in programmazione C/Socket in Linux
- 22. Buona lettura su programmazione Socket Unix/Linux?
- 23. Raw Socket Linux invia/riceve un pacchetto
- 24. accesso socket raw come utente normale su linux 2.4
- 25. Come eseguire server socket php in hosting linux
- 26. Utilizzo di Auto e Lambda per gestire il segnale?
- 27. Node.js: come svuotare il socket?
- 28. Come posso gestire un demone basato su Python su Linux?
- 29. Descrittori di socket e file
- 30. Conoscenza di qualsiasi libreria di socket multipiattaforma (Windows e Linux) in C?
Nessun contesto a questa domanda, qual è la vostra intenzione? – Kris
Ne ha davvero bisogno? Sto solo chiedendo le migliori pratiche ... – user3790882
@ user3790882 _ 'sto solo chiedendo le migliori pratiche'_ Dovresti essere un po' più elaborato su questo punto però: P ... –