Come posso controllare se un cliente disconnesso attraverso Winsock in C ++?
Domanda
Come posso controllare se un cliente scollegato attraverso Winsock in C ++?
Soluzione
di Beej Programming Guide della rete
se si chiama recv in modalità di blocco e ritorna con 0 byte leggono, il socket è disconnesso, altrimenti attendere per i byte da ricevere.
Look in questo FAQ 2.12
esempio da selezionare su questa pagina .
int nRet;
if(( nRet = select( 0, &fdread, NULL, NULL, NULL )) == SOCKET_ERROR )
{
// Error condition
// Check WSAGetLastError
}
if( nRet > 0 )
{
// select() will return value 1 because i m using only one socket
// At this point, it should be checked whether the
// socket is part of a set.
if( FD_ISSET( s, &fdread ))
{
// A read event has occurred on socket s
}
}
Altri suggerimenti
Si può dire solo se un socket TCP è 'scollegato' tentando di inviare i dati. Questo perché la progettazione del protocollo è tale che si suppone per consentire interruzioni temporanee tra coetanei. Quindi, se ci si connette da A via via R1 R2 R3 via a B e inviare i dati per un po 'e poi interrompere l'invio si potrebbe staccare R2-> R3 (per esempio) e né A né B sarebbero accorti (o cura). Se poi collegato R2-> R4 e R4-> R3 e poi ha tentato di inviare i dati tra A e B, allora le cose sarebbero 'solo di lavoro' e che non avevo mai sapere. Se, tuttavia, si è tentato di inviare i dati quando R2-> R3 è stato scollegato allora si sarebbe (finalmente, dopo tutti i tentativi di livello TCP) ottiene un errore di nuovo.
Ora, alcuni sistemi operativi possono essere in grado di avvisare l'utente del fatto che la scheda di rete locale non è attualmente connesso e si potrebbe usare quella di dire "Non sono più collegato al mio pari", ma non vorrei consigliarlo.
Se avere i vostri coetanei sanno quando le connessioni vengono 'rotti' importante quindi utilizzare un messaggio di livello di applicazione 'ping' per inviare di tanto in tanto dei dati tra i peer o utilizzare il protocollo TCP keep-alive. Personalmente mi piacerebbe andare per i messaggi ping ...
Modifica Naturalmente tutto ciò che è supponendo che si desidera sapere se è ancora possibile inviare i dati su una connessione, dopo tutto, ti si dice quando il client non è più sta inviando perché il vostro letture tornerà 0 byte e non si sa quando si disconnette il suo lato di invio perché i vostri scrive fallirà; Sapete anche quando si spegne il PC sia sul lato di invio o RECV della propria estremità della connessione ...
Credo che avrei dovuto bloccato con risposta reazione istintiva iniziale di "definire disconnesso";)
Ci sono alcuni modi diversi, ma il più comune è quello di verificare il risultato di una trasmissione o comando di ricezione:
nReadBytes = recv(sd, ReadBuffer, BufferSize, 0);
if (nReadBytes == SOCKET_ERROR)
{
//error
}
nSendBytes = send(sd, WriteBuffer, BufferSize, 0);
if (nSendBytes == SOCKET_ERROR)
{
//error
}
Altri esempi (completo di controllo degli errori, sia client che server) qui:
Se il risultato di send () o recv () è rendimenti SOCKET_ERROR e WSAGetLastError () WSAECONNRESET il cliente si è disconnesso.
Da MSDN:
WSAECONNRESET
Connection reset by peer.
Una connessione esistente veniva chiusa forzatamente dall'host remoto. Questo normalmente i risultati se l'applicazione pari sull'host remoto è improvvisamente fermato, l'host viene riavviato, l'host o rete remota interfaccia è bloccata, o l'host remoto utilizza un disco di chiusura (vedi setsockopt per ulteriori informazioni sull'opzione SO_LINGER sul telecomando socket). Questo errore può inoltre verificarsi se una connessione è stata interrotta a causa di keep-alive attività rilevare un errore durante una o più operazioni sono in corso. Le operazioni che erano in corso non riescono con WSAENETRESET. Le operazioni successive non riescono con WSAECONNRESET.
Questo funziona anche con i socket non bloccanti.
int r = recv(sock, NULL, 0, 0);
if(r == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){
//client has disconnected!
}