AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi TIdTCPServer: OnExecute-Schleife trotz Disconnect
Thema durchsuchen
Ansicht
Themen-Optionen

TIdTCPServer: OnExecute-Schleife trotz Disconnect

Offene Frage von "Windwalker"
Ein Thema von Windwalker · begonnen am 4. Sep 2009 · letzter Beitrag vom 5. Sep 2009
Antwort Antwort
Windwalker

Registriert seit: 9. Mär 2009
72 Beiträge
 
#1

TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 11:04
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:
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);
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.

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.
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 11:58
.. so ganz verstehe ich das nicht.

onExecute und Endlosschleife.

Sollte onExecute ncht ungefähr so gestrickt sein:

(Beispiel aus der Hilfe)
Delphi-Quellcode:
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;
Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#3

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 12:08
Also meine Excutes sehen sinngemäß meist so aus:
Delphi-Quellcode:
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);
Ich denke mal du hast die beiden Checks vergessen.
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
Windwalker

Registriert seit: 9. Mär 2009
72 Beiträge
 
#4

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 12:44
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:
Jede Verbindung, die ein TIdTCPServer entgegen nimmt, startet einen eigenen Thread. Und dieser Thread hat eben eine OnExecute Prozedur. Diese wird so lange wiederholt aufgerufen, wie die Verbindung besteht.

Und weil sich dein Programm aufhängt:
Ich rate mal, bau ein

Sleep(1); am Ende der OnExecute Prozedur ein.
Also scheint meine Verbindung noch zu bestehen, ob ich bei der Verarbeitung meines Disconnect-Kommandos ein
client.Context.Connection.Disconnect(True); mache.

Über weitere Hilfe freue ich mich sehr!

Danke,
Sascha.
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#5

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 12:52
Hallo,

kanst Du Deine OnExecute und OnDisconnet Methoden
hier zeigen?

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Windwalker

Registriert seit: 9. Mär 2009
72 Beiträge
 
#6

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 12:59
Klar!

OnExecute:
Delphi-Quellcode:
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;
Das OnDisconnect:
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:
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;
Das Disconnect, welches aus bearbeite_anfrage, beim Eintreffen eines Disconnect-Kommandos aufgerufen wird:
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;
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#7

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 4. Sep 2009, 19:15
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:
procedure TForm1.myOnExecute(aContext: TIdContext);
begin
  while aContext.Connection.Connected do
    sleep(10);
end;
Wird nun die Verbindung vom Client beendet, beendet sich auch die onExecute Methode.
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
Klaus
  Mit Zitat antworten Zitat
quantum

Registriert seit: 15. Apr 2006
Ort: Kassel
64 Beiträge
 
Delphi XE Professional
 
#8

Re: TIdTCPServer: OnExecute-Schleife trotz Disconnect

  Alt 5. Sep 2009, 12:58
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.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz