2012-09-13 11 views
14

Ho un'applicazione che deve inviare alcuni dati a un server in un dato momento. Il modo più semplice sarebbe chiudere la connessione e riaprirla quando voglio inviare qualcosa. Ma voglio mantenere aperta la connessione in modo che quando voglio inviare i dati, io per prima cosa controllare la connessione di utilizzare questa funzione:Verifica se la presa è collegata o meno

bool is_connected(int sock) 
{ 
    unsigned char buf; 
    int err = recv(sock,&buf,1,MSG_PEEK); 
    return err == -1 ? false : true; 
} 

La parte negativa è che questo non funziona. Si blocca quando non ci sono dati da ricevere. Cosa posso fare? Come posso verificare se la connessione è ancora aperta?

+3

http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c – BoBTFish

risposta

17

Non controllare prima e quindi inviare. È uno sforzo inutile e non funzionerà comunque - lo stato può cambiare tra quando controlli e quando invii. Fai solo ciò che vuoi e gestisci l'errore se fallisce.

Per controllare lo stato, utilizzare:

int error_code; 
int error_code_size = sizeof(error_code); 
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); 
+1

Vero ... ma a volte è utile verificare se un socket è ancora connesso. Impostarlo su non-block e quindi leggere con peek_msg è un buon modo per ottenere un codice di errore per verificare che il socket sia ancora connesso. –

+2

@RafaelBaptista Perché? * Usando * controllerà. Il primo test non può funzionare in modo affidabile, per la ragione per cui David dà sopra. – EJP

+0

@EJP: Voglio verificare che la connessione client sia attiva, quindi non spreco risorse nel caso in cui non lo fosse. – che

12

È necessario abilitare il comportamento non bloccante, impostando O_NONBLOCK utilizzando fcntl. Un modo semplice, ma non standard per fare una lettura non-blocking sarebbe quella di utilizzare:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT); 

Successivamente, è must controllo errno se fallisce. Esso può fallire con EAGAIN o può riuscire con EBADF o ENOTCONN ecc


Ovviamente, il modo più semplice e più pulito per affrontare questo sarebbe di evitare "dimenticare" se la presa è collegato o meno. Noterai se lo zoccolo si disconnette quando lo recv restituisce 0 o send restituisce EPIPE.

+2

questo non rilevare tutti i guasti di connessione. Solo un send() può farlo. – EJP

+0

@EJP Questo è vero in effetti. Stavo solo migliorando la soluzione dell'op. Quello che stai suggerendo è l'unica soluzione a prova di proiettile, ma comporta l'invio. – cnicutar

2

L'utilizzo predefinito di TCP non consente il rilevamento molto tempestivo di prese non funzionanti (al di fuori della normale chiusura), quindi suggerirò che una funzione "is_connected" come questa è largamente inutile per tutti gli scopi pratici. Prendi in considerazione l'implementazione di un livello di applicazione keep-alive e traccia se è vivo in base a risposte tempestive (o alla mancanza di esse).

modifica: dopo la pubblicazione vedo il collegamento di BoBTFish, che è effettivamente la stessa cosa.

Problemi correlati