![]() |
Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Hallo,
gibt es eine saubere Lösung Client verbindungen zu trennen wenn der TidTCPServer geschlossen wird? Ein einfaches idTCPServer1.active := False reicht hier scheinbar nicht, denn dann friert das Programm ein. Ganz selten bekomme ich aber auch mal die Meldung "Die Verbindung wurde erfolgreich geschlossen" aber auch wirklich nur sehr selten und das Programm friert dennoch ein. Wenn jeder Client von sich aus die Verbindung beendet und ich dann das Programm schliesse lässt es sich auch ohne Probleme beenden. Die Suche und auch alle Demo Programme die ich gefunden habe bringen mich dabei leider auch nicht weiter. Im Form Close habe ich bereits alles bisher gefundene einmal probiert leider bisher ohne Erfolg. Beende ich das Programm ohne vorher idTCPServer1.active := False aufzurufen endet es in eine access violation. Denke mal das die Threads natürlich noch laufen werden und sie daher kommt. Ich poste einfach mal mein FormClose
Delphi-Quellcode:
Egal was ich versuche der Server trennt den Client nicht und der Client bekommt auch keine Meldung über einen disconnect.
procedure TServerMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
var I: Integer; begin if IdTCPServer.Active then begin // while IdTCPServer.Contexts.LockList.Count > 0 do // begin // TIdContext(IdTCPServer.Contexts.LockList[0]).Connection.IOHandler.CloseGracefully; // end; Memo1.Lines.Add(Format('%d connected Clients', [IdTCPServer.Contexts.LockList.Count])); if IdTCPServer.Contexts.LockList.Count > 0 then begin for I := 0 to IdTCPServer.Contexts.LockList.Count -1 do begin //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.IOHandler.CloseGracefully; //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.DisconnectNotifyPeer; //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.Disconnect; //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.IOHandler.DiscardAll; //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.IOHandler.CheckForDisconnect(False, True); //TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.CheckForGracefulDisconnect(False); end; end; //IdTCPServer.Contexts.UnlockList; IdTCPServer.Active := False; end; end; Rufe ich TIdContext(IdTCPServer.Contexts.LockList[i]).Connection.Disconnect; auf dann wird am Server das OnDisconnect aufgerufen aber das war es dann auch schon. Vielen Dank im vorraus wenn mir jemand bei dem Problem helfen könnte, ich selbst bin ratlos. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Zitat:
* eine in OnExecute aufgetretene Indy-Exceptions wird abgefangen (zum Beispiel durch ein leeres except ... end) * die Anwendung blockiert wenn in OnExecute ein Deadlock auftritt, zum Beispiel im Zusammenhang mit dem VCL Thread Beispiel: Zitat:
![]() Übersetzt: Zitat:
Siehe auch: ![]() |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Hallo,
ich habe nun das FormClose so übernommen und bekomme neben der Meldung der erfolgreichen Beendigung folgende: Zitat:
Delphi-Quellcode:
Wenn ich nun den Server außerhalb der IDE starte kommt die Fehlermeldung nicht...
procedure TStringServerForm.IdTCPServer1Execute(AContext: TIdContext);
var LLine: String; ID: Integer; begin if IdTCPServer1.Active then begin //TIdNotify.NotifyMethod( ShowStartServerdMessage ); //LLine := AContext.Connection.IOHandler.ReadLn(TIdTextEncoding.Default); ID := Integer(AContext.Connection.Socket); LLine := AContext.Connection.IOHandler.ReadLn(); Memo1.Lines.Add(Format('[%.10d]: %s', [ID, LLine])); AContext.Connection.IOHandler.WriteLn('OK'); //TIdNotify.NotifyMethod( StopStartServerdMessage ); end; AContext.Connection.IOHandler.CheckForDisconnect(False, True); AContext.Connection.CheckForGracefulDisconnect(False); end; |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Die sauberste Art eine TCP-Verbindung zu trennen ist dem Partner einen Quit-Befehl zu senden.
Man findet diesen Weg sehr häufig in bekannten Internetprotokollen. Bei FTP sendet der Client z.B. dem Server eine QUIT-Message und der Server beendet dann die TCP-Verbindung. Dies gibt beiden Teilnehmern die Möglichkeit sauber alle Aufgaben abzuschliesen. Natürlich sollte sowohl der Client als auch der Server eine Trennung der Verbindung (z.B. abgezogenes Ethernetkabel) ohne Endlosschleife überleben. Allerdings kann ein Teilnehmer eine unterbrochene TCP-Verbindung nur dann entdecken, wenn er entweder selbst etwas sendet oder wenn er das FIN-Paket der Gegenstelle empfangen wurde. Auf jeden Fall ist es empfehlenswert einen Quit-Befehl im Datenprotokoll vorzusehen. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Es geht ja genau um den Fall das die Verbindung aus unbekannten Gründen beendet wurde,eben durch gezogenes Kabel, Verlust der Internetverbindung, Rechner Absturz o.ä.
Ich habe bisher unter Windows immer direkt mit den Sockets gearbeitet und da konnte man vor dem Beenden des Servers aus Serversicht alle Clientverbindungen trennen, Die Indys haben ja auch im Client ein OnDisconnect, das wurde in egal welchem Versuch Serverseitig die Verbindung zu trennen nie aufgerufen. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Zitat:
Diese wird aus der Methode TIdTCPConnection.Disconnect aufgerufen, also nachdem der Client die Verbindung zum Server geschlossen hat. Mit dem serverseitigen Schliessen hat diese Methode nichts zu tun. Auf der Client-Seite kann nur mit einem kontinuierlichen Read auf der Connection das serverseitige Schliessen der Verbindung erkannt werden. Im Fall der Indy TIdTCPClient Klasse würde clientseitig eine Exception (EIdConnClosedGracefully oder ein EIdSocketError) ausgelöst, wenn das Read vom Socket nicht weiter möglich ist. Die Behandlung einer "Read Timeout" Exception muss bei diesem Verfahren auf der Clientseite u.U. auch vorgesehen werden, diese bedeutet aber nur, dass keine Daten empfangen wurden, und nicht, dass der Server die Verbindung getrennt hat. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Zitat:
Das "if IdTCPServer1.Active" then ist nicht erforderlich, da der Server den Eventhandler nicht mehr aufrufen wird wenn Active := False ist. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Das ist alles schon klar. Es handelt sich hier ja nur um eine Testanwendung und es ist auch nur ein Client verbunden.
Ich wollte halt alles mögliche ausprobieren was ich beim Suchen gefunden habe. Dennoch wird damit das eigentliche Problem ja nicht gelöst. Das letzte war einfach nur im OnClose der Form Active auf False zu setzen und das Programm hing. Derzeit ist es so das die Fehlermeldungen nur innerhalb der IDE auftauchen. Starte ich das Programm ohne IDE läuft es wunderbar. Später ist es in einer Konsolenanwendung auf Linux und da wird auch nichts angezeigt sondern nur intern ausgewertet. Wie gesagt ich hatte so etwas schon mit den Sockets programmiert. Stammt alles noch vom Bin-Protokoll von Hagen glaub ich wars. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Gibt es hier mittlerweile eine funktionierende Lösung für Indy 10? Ich stehe nämlich genau vor dem gleichen Problem. Meine OnExecute Methode des Servers ist noch vollkommen leer, da ich erst im Aufbau des Servers bin. Sobald alle Clients von selbst disconnecten, wird auch die Anwendung sauber geschlossen.
Wenn ich die Möglichkeit habe, jedem Client vorher eine Quit Befehl zu senden, wie sx2008 es auch bereits erwähnt hat, dann werde ich das natürlich machen. Mir geht es allerdings vorangig um den Fall, dass ich den Server ohne den Quit Befehl beenden muss (warum auch immer). Wäre für eine funktionierende Lösung sehr dankbar. |
AW: Indy 10.6.5040 TCPServer Serverschliessen und Client Verbindungen trennen
Gemeinde.
Und ich habe ebenfalls genau dasselbe Problem oder fast. Mein Client verbindet sich zum Server und der Server wird aus irgendwelchen Gründen unsauber beendet. Die Verbindungen zu den verbundenen Clients wird also nicht korrekt beendet. Selbst mit ReadTimeout hängt sich das Programm auf und befindet sich in einer Endlosschleife OBWOHL eine AV geworfen werden müsste:
Delphi-Quellcode:
while not Terminated do
begin Sleep(5000); IdTCPClient.ReadTimeout := 2000; IdTCPClient.IOHandler.ReadTimeout := 2000; if IdTCPClient.Connected then begin try s := IdTCPClient.IOHandler.ReadLn; except on E: Exception do WriteLn(PChar(E.ToString)); break; end; end else begin break; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz