![]() |
TIdTCPServer: OnExecute-Schleife trotz Disconnect
Hallo,
ich teste gerade einen von mir implementierten Windows-Dienst über Telnet. Über Telnet simuliere ich einen Client und schicke dem IdTCPServer Kommandos. Die werden auch alle gut erkannt. Jedoch habe ich ein Problem mit dem Disconnect. Wenn ich vom Client das Disconnect-Kommando sende, erkennt dieses mein Dienst auch und ruft die richtige Prozedur auf, um den Disconnect durchzuführen. Hier führe ich u.a. folgende Anweisungen aus:
Delphi-Quellcode:
Mein Telnet-Fenster schließt sich auch korrekt, jedoch wird beim IdTCPServer weiterhin in einer Endlosschleife das OnExecute-Event ausgelöst, was meinen Dienst zu ständigen Fehlermeldungen bringt, da er den Client nicht mehr in seiner Client-Liste führt.
log( 'Beende Verbindunge zu Host=' + client.host+ ' Port=' + IntToStr(client.Port)+' ....',1);
// dem client mitteilen das jetzt die verbindung beendet wird senden(client,disconnect_zeichen); client.Context.Connection.Disconnect(True); // Den Client aus der Liste verbundener Clients löschen Tclient(client_list.Objects[i]).free; client_list.Delete(i); log('disconnect: Verbindung beendet',1); Das eigentliche OnDisconnect-Event wird erst dann ausgelöst, wenn ich den Dienst wieder beende. Wie kann ich das ständige Triggern des OnExecute-Ereignisses verhindern und ein korrektes Auslösen des OnDisconnect-Events herbeiführen? Danke für die Hilfe! Sascha. |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
.. so ganz verstehe ich das nicht.
onExecute und Endlosschleife. Sollte onExecute ncht ungefähr so gestrickt sein: (Beispiel aus der Hilfe)
Delphi-Quellcode:
Grüße
TMyForm.MyServerExecute(AContext: TIdContext);
var lCmd: string; begin lCmd := Trim(AContext.Connection.IOHandler.ReadLn); if AnsiSameText(lCmd, 'HELP') then begin AContext.Connection.IOHandler.WriteLn('HELP'); AContext.Connection.IOHandler.WriteLn('QUIT'); AContext.Connection.IOHandler.WriteLn('GETTIMESTAMP'); AContext.Connection.IOHandler.WriteLn(''); end else if AnsiSameText(lCmd, 'QUIT') then begin AContext.Connection.IOHandler.WriteLn('Goodbye...'); AContext.Connection.IOHandler.WriteLn(''); AContext.Connection.Disconnect; end else if AnsiSameText(lCmd, 'GETTIMESTAMP') then begin AContext.Connection.IOHandler.WriteLn( FormatDateTime(Now, 'yyyy-mm-ddThh:nn:ss.zzz')); AContext.Connection.IOHandler.WriteLn(''); end; end; Klaus |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Also meine Excutes sehen sinngemäß meist so aus:
Delphi-Quellcode:
Ich denke mal du hast die beiden Checks vergessen.
repeat
If AThread.Connection.InputBuffer.Size > 0 then begin //... end; AThread.Connection.CheckForDisconnect(False); AThread.Connection.CheckForGracefulDisconnect(False); SleepEx(1, true); until (not AThread.Connection.Connected); |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Danke schonmal!
Aber leider bringt's das bei mir nicht. Zum einen habe ich keinen "AThread"-Parameter, sondern "AContext" und dieser besitzt in seiner Connection kein CheckForDisconnect, sondern nur das CheckForGracefulDisconnect (ich nutze Delphi 2006). Aber auch, wenn ich nur das CheckForGracefulDisconnect und das Sleep einbaue, wird das OnExecute-Event immer wieder erneut ausgelöst. Ich habe bei meiner Recherche dazu auch folgendes gefunden: Zitat:
Delphi-Quellcode:
mache.
client.Context.Connection.Disconnect(True);
Über weitere Hilfe freue ich mich sehr! Danke, Sascha. |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Hallo,
kanst Du Deine OnExecute und OnDisconnet Methoden hier zeigen? Grüße Klaus |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Klar!
OnExecute:
Delphi-Quellcode:
Das OnDisconnect:
procedure TmyService.IdTCPServerExecute(AContext: TIdContext);
var cli :TClient; s, s1 : string; i, laenge :integer; fehler : boolean; ThreadKey : string; begin // Hier reagiert der Server auf eingehende Nachrichten try fehler := FALSE; ThreadKey := get_key(AContext); i:=client_list.IndexOf(ThreadKey); if i >= 0 then begin cli := TClient(client_list.objects[i]); log('Anfrage von Client '+cli.host,0); while (not fehler) and (AContext.Connection.Connected) do begin try s1 := AContext.Connection.IOHandler.ReadString(7); laenge := StrToIntDef(s1, -1); log('Länge des Pakets: '+s1,0); if laenge>0 then begin s1 := AContext.Connection.IOHandler.ReadString(laenge); cli.anfrage := s1; Extrahiere_anfrage(cli.anfrage,s); if s<>'' then begin log('Anfrage: '+s,0); bearbeite_anfrage(s,cli); end; end else begin log('Längenangabe des zu empfangenden Buffers ist fehlerhaft ('+s1+')',1); fehler := TRUE; end; except on e :EIdConnClosedGracefully do begin log('ConnClosedGracefully',1); fehler := TRUE; end; on e :Exception do begin log('Fehler beim Lesen von Host='+cli.host+ ' Port='+IntToStr(cli.port),1); log(e.Message,9); log(e.ClassName,9); fehler := TRUE; disconnect(cli); end; end; end; // While end else log('Client nicht in Liste',1); except on e:exception do log('Feher in der Executeroutine des Servers: '+e.Message,9); end; end;
Delphi-Quellcode:
procedure TmyService.IdTCPServerDisconnect(AContext: TIdContext);
var Cli:TClient; i:integer; s:string; begin // hier wird ein Client abgemeldet log('OnDisconnect: Client-List Size: '+IntToStr(client_list.Count),2); if AContext <> nil then begin Cli:= nil; s:= get_key(AContext); log('OnDisconnect des Clients: '+s,1); ThreadLock_ClientListe.Enter; try i:= client_list.IndexOf(s); log('OnDisconnect: Client-Index='+IntToStr(i),2); if (i > -1) then begin log('OnDisconnect: Index > -1 --> Disconnect aufrufen'+s,1); Cli:= TClient(client_list.objects[i]); end; finally ThreadLock_ClientListe.leave; end; if Cli <> nil then begin disconnect(Cli); end; end; end; Und zwei Methoden, die im OnExecute benutzt werden: bearbeite_anfrage:
Delphi-Quellcode:
Das Disconnect, welches aus bearbeite_anfrage, beim Eintreffen eines Disconnect-Kommandos aufgerufen wird:
procedure TmyService.bearbeite_anfrage(var anfrage: String;
cli: TClient); var bearbeitet : boolean; msg : string; begin // hier werden die von Clients eintreffenden Nachrichten bearbeitet log('Bearbeite Anfrage: '+cli.anfrage,2); bearbeitet := False; // hier die Nachrichten auswerten, z.B. if anfrage = schreibe_in_log then begin lies_nachricht(cli.anfrage, msg); log('WRITETOLOG: '+msg, 9); bearbeitet := True; end else if anfrage = disconnect_client then begin // disconnect des clients kommt gleich --> aus liste rausschmeißen disconnect(cli); end else begin log('Befehl '''+anfrage+''' nicht verstanden.',9); end; if bearbeitet then senden(cli,anfrage); anfrage:= ''; end;
Delphi-Quellcode:
procedure TmyServiceService.disconnect(cli: Tclient);
var i:integer; begin (* Client wird aus der Liste entfernt und ein Disconnect durchgeführt *) try try ThreadLock_ClientListe.Enter; if client_list.Find(get_key(cli.Context),i) then begin log( 'Beende Verbindunge zu Host=' + cli.host+ ' Port=' + IntToStr(cli.Port)+' ....',1); // dem client mitteilen das jetzt die verbindung beendet wird senden(cli,disconnect_zeichen); cli.Context.Connection.DisconnectNotifyPeer; Tclient(client_list.Objects[i]).free; client_list.Delete(i); log('disconnect: Verbindung beendet',1); end; finally ThreadLock_ClientListe.Leave; end; except on e:exception do log('Fehler beim disconnect: '+e.Message,9); end; end; |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Guten Abend,
ich habe mal ein paar kleine Test mit einem simplen Server und Client gemacht. Pro verbunden Client wird ein onExecute Thread eröffnet (sichtbar im Taskmanager), wenn ich nun in der onExecute folgende Schleife habe:
Delphi-Quellcode:
Wird nun die Verbindung vom Client beendet, beendet sich auch die onExecute Methode.
procedure TForm1.myOnExecute(aContext: TIdContext);
begin while aContext.Connection.Connected do sleep(10); end; Der Thread wird beendet und gut ist. Ein onDisconnect Methode habe ich nicht benutzt. Was bei Dir schief läuft - keine Ahnung. Grüße Klaus |
Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect
Ich bin mir ziemlich sicher, es liegt an den verschluckten Exceptions.
Entferne mal das äußere "try..except..end" Konstrukt im OnExecute-Handler oder füge wenigestens "raise" als letzten Befehl unter "except" ein. Wenn ich mich recht erinnere, beendet der Indy-Server den Thread nur wenn er mit einer Exception konfrontiert wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 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