Frage

Hoffentlich jemand kann uns helfen, wenn wir so weit wie Untersuchungen sind Erreichen gehen!

Wir haben eine einfache asynchrone Socket-Server in C # geschrieben habe, die Verbindungen von einer ASP.NET Web-Anwendung akzeptiert, wird eine Nachricht gesendet wird, führt einige Verarbeitung (in der Regel gegen eine DB, sondern auch andere Systeme auch) und sendet dann eine Antwort zurück an den Client. Der Kunde ist verantwortlich für die Verbindung zu schließen.

Wir haben Probleme wurden mit denen, wenn das System über einen langen Zeitraum unter hoher Last (Tage in der Regel), CLOSE_WAIT Buchsen auf der Server-Box (netstat -a) in einem Ausmaß aufzubauen, dass der Prozess nicht akzeptieren alle weiteren Verbindungen. An diesem Punkt müssen wir den Prozess hüpfen und aus läuft es wieder.

Wir haben versucht, einige Belastungstests unserer ASP.NET-Anwendung ausgeführt wird, um zu versuchen, das Problem zu reproduzieren (weil aus dem Code einig Frage Folgern nicht möglich war). Wir denken, wir haben es geschafft, diese und endete mit einem Packet Trace des Problems selbst als Socket manifestiert in der Socket-Servers der Protokolle:

  

System.Net.Sockets.SocketException: Eine bestehende Verbindung wurde gewaltsam von der Remote-Host geschlossen   bei System.Net.Sockets.Socket.BeginSend (Byte [] Puffer, Int32 Offset, Int32 Größe, Socketsocket, AsyncCallback Rückruf, Objektzustand)

Ich habe versucht, das Problem aus dem Paket Spur zu reproduzieren als ein einzelner direkt Gewinde Prozess mit dem Socket-Server im Gespräch (mit dem gleichen Code der ASP.NET app tut) und nicht in der Lage ist.

Hat jemand bekam irgendwelche Vorschläge des nächsten Dinge zu versuchen, überprüfen oder offensichtliche Dinge, die wir falsch machen kann?

War es hilfreich?

Lösung

Blick auf das Diagramm

http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg

Der Client hat die Verbindung geschlossen durch eine enge () aufrufen, die FIN an den Server-Socket gesendet, die die FIN und den Zustand von denen CLOSE_WAIT geändert jetzt ACKed, und bleibt so, wenn der Server-Probleme close () auf, dass rufen Buchse.

Ihr Server-Programm muss erkennen, ob der Client die Verbindung abgebrochen hat, und schließen Sie dann () sofort den Port freizugeben. Wie? Siehe lesen (). Beim Lesen End-of-Datei (im Sinne von FIN empfangen wird), wird Null zurückgegeben.

Andere Tipps

Wenn Ihr Server Akkumulieren CLOSE_WAIT Steckdosen dann ist es nicht seine Fassung zu schließen, wenn die Verbindung hergestellt ist. Wenn Sie einen Blick auf das Zustandsdiagramm in dem Kommentar zu Chris' Post nehmen werden Sie feststellen, dass CLOSE_WAIT Übergänge sehen LAST_ACK sobald der Socket geschlossen ist und die FIN gesendet wurde.

Sie sagen, dass es komplex ist zu bestimmen, wo dies aufgrund der Asynchron Natur zu tun? Dies sollte kein Problem sein, sollten Sie die Steckdose schließen, wenn der Rückruf von Ihrem recv 0 Bytes zurückgibt (vorausgesetzt, Sie haben nichts anderes zu tun, wenn Ihr Kunde seine Seite der Verbindung schließt). Wenn Sie sich Sorgen machen müssen weiterhin hier dann eine Shutdown (recv) zu senden und eine Notiz machen, dass Ihr Kunde geschlossen hat, sobald Sie das Senden fertig ein Shutdown tun (senden) und ein Schließen.

Sie können sich einen neuen Lese in den Rückruf aus dem gelesenen Ausgabe, die 0 zurück, der anzeigt, dass der Client geschlossen hat und dies kann Probleme verursachen?

  

Der Kunde ist verantwortlich für die Verbindung zu schließen.

Sowohl der Client als auch der Server muss die Steckdose in der Nähe und Shutdown. Entweder der Kunde Finishing nicht die engen (unwahrscheinlich - da es müßte es Finalizerthread Lauf) oder der Server heruntergefahren wird nicht die Fassung (wahrscheinlich)

.
using (Socket s = new Socket(/* */)) {
  /* Do stuff */
  s.Shutdown(SocketShutdown.Both);
  s.Close();
}

Sie sollten nicht die Verantwortung nur die TCP-Sockets zu schließen, bis zu dem Client verlassen. Was passiert, wenn der Client-Prozess / Maschine abstürzt?

Im Idealfall sollten Sie eine Auszeit an der richtigen Stelle, so dass, wenn kein Verkehr auf einem verbundenen Socket nach einer bestimmten Zeit empfangen wird, dann wird es vom Server geschlossen wird.

Egal, was passiert, wenn alle Operationen auf dem Sockel des Kunden beendet haben, und es braucht keine weiteren Leseoperationen auf dem Sockel zu tun, soll der Kunde einen genauen Befehl ausgeben.

Diese Ausgabe von Schließbefehl, sagt einfach den Hörer (Server), dass die Verbindung zu heruntergefahren werden muss.

In einfachen Worten, wenn der Server wieder einen Lesebefehl ausgibt (listener.read () oder listener.beginread (...) in Asynchron-Modus), kehrt die Lese ein 0 Byte zu lesen, das an mir zeigt, dass die Steckdose muss vom Hörer geschlossen werden, wie alle anderen Operationen an der Steckdose durch den Kunden aufgehört hat.

CLOSE_WAIT die sollen für eine Weile hängen, um nach einer Steckdose geschlossen ist, wieder mit der gleichen Socket-Nummer zu verhindern und Pakete von der alten Verbindung zu empfangen. Dies wird Ihnen nur Trauer, wenn Sie öffnen und eine huuuuge Anzahl von Sockets wirklich schnell zu schließen.

EDIT -. Es sollte TIME_WAIT sein, nicht über CLOSE_WAIT

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top