2010-03-31 9 views
16

Auf der Client-Seite muss ich wissen, ob/wenn meine Socket-Verbindung unterbrochen wurde. Die Eigenschaft Socket.Connected gibt jedoch immer true zurück, auch nachdem die Serverseite getrennt wurde und ich versucht habe, Daten über diese Seite zu senden. Kann mir jemand helfen, herauszufinden, was hier vor sich geht? Ich muss wissen, wann ein Socket getrennt wurde.So erkennen Sie, wenn ein Socket getrennt wurde

 Socket serverSocket = null; 
     TcpListener listener = new TcpListener(1530); 
     listener.Start(); 
     listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result) 
     { 
      Debug.WriteLine("ACCEPTING SOCKET CONNECTION"); 
      TcpListener currentListener = (TcpListener)result.AsyncState; 
      serverSocket = currentListener.EndAcceptSocket(result); 
     }), listener); 


     Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is 
     clientSocket.Connect("localhost", 1530); 
     Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is 

     Thread.Sleep(1000); 
     serverSocket.Close();//closing the server socket here 
     Thread.Sleep(1000); 

     clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property. 
     Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE 
+0

Siehe http://stackoverflow.com/questions/722240/instantly-detect-client-disconnection-from-server-socket für die weitere Diskussion. – EricLaw

Antwort

0

wartet die clientSocket.Send() Methode auf das Paket, um entweder ack/nack'd zu sein?

Wenn nicht, fliegt Ihr Code in die nächste Zeile, während Socket noch versucht herauszufinden, was vor sich geht.

+0

Sie können nach dem Senden ein Thread.Sleep setzen. Egal wie lange Sie warten clientSocket.Connected bleibt True. – BowserKingKoopa

9

Nach einigen Tests scheint die Dokumentation für Socket.Connected falsch oder zumindest irreführend zu sein. clientSocket.Connected wird nur falsch, nachdem clientSocket.close() aufgerufen wird. Ich denke, dies ist eine Reminiszenz an die ursprüngliche C Berkeley Sockets API und ihre Terminologie. Ein Socket ist gebunden, wenn ihm eine lokale Adresse zugeordnet ist, und ein Socket ist verbunden, wenn ihm eine entfernte Adresse zugeordnet ist. Obwohl die entfernte Seite die Verbindung geschlossen hat, hat der lokale Socket immer noch die Assoziation und ist somit immer noch "verbunden".

Hier ist jedoch eine Methode, die funktionierts:

!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0) 

Es ist auf dieser Tatsache beruht, dass eine geschlossene Verbindung, gut lesbar gekennzeichnet sein wird, auch wenn keine Daten verfügbar sind.

Wenn Sie feststellen möchten, dass z. B. beschädigte Netzwerkkabel oder Computer abrupt ausgeschaltet werden, ist die Situation etwas komplexer. Unter diesen Bedingungen empfängt Ihr Computer niemals ein Paket, das anzeigt, dass der Socket geschlossen wurde. Es muss erkennen, dass die entfernte Seite verschwunden ist, indem es Pakete sendet und bemerkt, dass keine Antwort zurückkommt. Sie können dies auf Anwendungsebene als Teil Ihres Protokolls ausführen oder Sie können die TCP KeepAlive-Option verwenden. Die Verwendung von TCP Keep Alive von .NET ist nicht besonders einfach. Sie sind wahrscheinlich besser dran, einen Keep-Alive-Mechanismus in Ihr Protokoll zu integrieren (alternativ können Sie eine separate Frage stellen für "Wie aktiviere ich TCP Keep Alive in .NET und setze das Keep-Alive-Intervall?").

+0

socket.Poll (0, SelectMode.SelectRead) gibt immer wahr für mich auch nach der Server-Seite Verbindung geschlossen wurde. – BowserKingKoopa

+0

Auch die Msdn docs sagen, dass die Umfrage-Methode nicht bestimmte Bedingungen „wie ein gebrochenes Netzwerkkabel, oder dass die Remote-Host wurde ungracefully heruntergefahren“ erkennen kann. Ich möchte nur wissen, ob der serverseitige Socket da ist oder nicht, es ist mir egal, warum es nicht da ist. – BowserKingKoopa

+0

@BrowserKingKoopa: Whoops! Der Code, den ich ursprünglich gepostet habe, hat getestet, dass der Socket * getrennt * ist. Ich habe es behoben. Wenn die Remote-Seite getrennt hat, Poll() gibt true zurück, aber socket.Available wird 0. ich auch einen Absatz über den Umgang mit unterbrochenen Netzwerkkabeln hinzugefügt. –

3

Vielleicht Lösung ist es, einige Dummy-Daten durch sie zu senden und zu überprüfen, ob es Timeout?

2

Ich empfehle, die Sprache der höheren Ebene zu streichen und zu erkunden, was auf der unteren IO passiert.

Die niedrigste, die ich erforscht habe, war während des Schreibens isectd (auf Sourceforge finden). Mit dem Systemaufruf select() wird ein Deskriptor für einen geschlossenen Socket lesbereit, und wenn isectd den recv() versucht, kann der Verbindungsstatus des Sockets bestätigt werden.

Als eine Lösung, empfehle ich nicht schreiben Sie Ihre eigenen Socket IO und verwenden Sie jemandes Middleware. Es gibt viele gute Kandidaten da draußen. Vergessen Sie nicht, auch einfache Warteschlangen zu berücksichtigen.

PS. Ich hätte alle oben genannten URLs zur Verfügung gestellt, aber mein Ruf (1) erlaubt es nicht.

4

Schreiben Sie einfach wie gewohnt in Ihre Steckdose. Sie werden wissen, wann die Verbindung durch die Ausnahme getrennt wurde, die besagt, dass Ihre Daten nicht zugestellt werden konnten.

Wenn Sie nichts zu schreiben haben ... dann wen interessiert es, wenn es getrennt ist? Es kann jetzt getrennt werden, aber komm zurück, bevor du es brauchst - warum solltest du es abreißen und dann eine Wiederverbindung wiederholen, bis die Verbindung repariert ist ...vor allem, wenn du sowieso nichts zu sagen hast?

Wenn es Sie stört, implementieren ein in Ihrem Protokoll am Leben zu halten. Dann haben Sie etwa alle 30 Sekunden etwas zu sagen.

+0

+1, wenn der Server alle Daten gesendet und es wird nicht am Leben halten sollten Buchse schließen und Client sollte es propertly behandeln. von der Seite des Clients, wenn es alle Daten erhielt, die es wollte, schließt es auch Verbindung, der Server wird es behandeln. Sie sollten nur Ausnahmen abfangen am Ende/s.Send zu wissen, wenn jemand getrennt ist, Poll wird auch Ausnahme auf getrennten Socket werfen – hoodoos

+0

Sockets funktionieren in beide Richtungen, das Hauptproblem ist, wenn Sie Push mit dem Socket verwenden, aber der Sockel ist d/c ohne dass du es weisst, so bekommst du keine daten wie beim lesen des netzwerkstreams gibts daten aber kein fehler. –

Verwandte Themen