Newsgroup: it.comp.lang.visual-basic
Titolo: Accorgersi della disconnessione di un socket

Ciao a tutti,
 
ho un programma fatto in VB2008 che utilizza degli oggetti di tipo 
System.Net.Sockets.TCPListener per rimanere in ascolto di connessioni TCP da 
parte di clients, e una volta ricevuta la richiesta di connessione, se ci 
sono le condizioni, la richiesta viene accettata usando il metodo 
AcceptSockect e da questo metodo viene restituito un oggetto di tipo 
System.Net.Sockets.Socket.
 
Vorrei essere in grado di "capire" quando la connessione viene persa, per un 
qualunque motivo.
 
Fin'ora ho utilizzato la seguente funzione:
 
Private Function IsConnected(ByVal target As System.Net.Sockets.Socket) As 
Boolean
 
   If target.Connected = False Then
 
       Return False
 
   Else
 
       Dim bState As Boolean = target.Poll(1, 
System.Net.Sockets.SelectMode.SelectRead)
 
       If bState And (target.Available = 0) Then
 
            Return False
 
       Else
 
            Return True
 
       End If
 
   End If
 
End Function
 
 
La quale funziona bene se il client si disconnette "per cause naturali", 
cioe' il programma viene chiuso, terminato, crashato ecc...
 
Non vengono rilevate pero' le disconnessioni dovute a spegnimento improvviso 
del pc (ad esempio per interruzione di alimentazione elettrica) o se la rete 
va giu' (ad esempio si spegne lo switch o scollego il cavo di rete).
 
Che posso fare?
 
Grazie e ciao... Maurizio 
 
 
__________ Informazioni da ESET NOD32 Antivirus, versione del database delle firme digitali 7851 (20130102) __________
 
Il messaggio è stato controllato da ESET NOD32 Antivirus.
 
www.nod32.it
 
 
 
 

Dopo dura riflessione, vbMizio ha scritto :

E' una cosa abbastanza nota.
Il TCP/Ip ha spesso queste latenze, del tipo che tu stacchi il cavo di 
rete e magari per mezzo minuto lui continua a dirti che IsConnected, 
oppure peggio resta 'appeso' a testare lo stato prima di risponderti.
Purtroppo non mi risulta ci siano soluzioni, è un problema che va oltre 
la normale programmazione ed entra nello stack del tcp/ip, quindi 
dipende molto anche dall'hardware e dai driver.
Una cosa che però si fa, è concepire un protocollo di ping nella 
comunicazione, quindi tipicamente chi abbia bisogno di sapere se la 
connessione è veramente aperta, effettua un invio periodico di un 
pacchetto a cui l'altro capo deve replicare con un ACK, con un timeout 
cortissimo. E' chiaro che se a fronte della caduta di connessione si 
deve intraprendere qualcosa di critico, in caso di esito negativo del 
ping occorre rieseguirlo con timeout superiore, per essere sicuri non 
si tratti di un normale rallentamento.
 
Alberto
 
 

 [...] Una cosa che però si fa, è concepire un protocollo di ping nella
comunicazione [...]
Uff, temevo di dover verificare la connessione tramite invii di messaggi 
"test".
Speravo proprio di poterlo evitare, mannaggia.
Vabbe', grazie ancora della risposta.


Risolto,
ho modificato il codice che avevo riportato, facendo in modo che, se la 
connessione risulta ancora attiva, eseguo sul socket una operazione di Send, 
la quale sembra andare a buon fine (cosa impossibile perche' la destinazione 
e' spenta o comunque sconnessa); questo pero' provoca, nel giro di circa 20 
secondi, che la chiamata al metodo Poll restituisca True (memorizzata nella 
variabile bState) e, dato che la proprieta' Available del socket e' uguale a 
0, la funzione nella sua interezza restituisca False
Riporto il codice modificato, dovesse essere utile a qualcuno.
 
If target.Connected =False Then
    Return False
Else
    Dim bState AsBoolean = target.Poll(1, 
System.Net.Sockets.SelectMode.SelectRead)
    If bState And (target.Available = 0)Then
       ReturnFalse
    Else
      ' Invio un messaggio. Se il socket e' disconnesso, verra' rilevata la 
disconnessione.
      ' Senza questo invio, rilevare la disconnessione e' molto piu' 
difficile.
      Dim bf(0)As Byte
      bf(0) = 0
      Dim sn As Integer = target.Send(bf)
      Return True
   End If
End If 
 
 
__________ Informazioni da ESET NOD32 Antivirus, versione del database delle firme digitali 7854 (20130102) __________
