Entwickler-Ecke

Internet / Netzwerk - Probleme mit Indy 10 und Client


gitguy - Mo 12.11.07 10:09
Titel: Probleme mit Indy 10 und Client
Hallo an alle!

Ich habe gestern erst mit Indy angefangen, bin also noch ganz neu.

Trotzdem hab ich ne Frage: Ich habe Indy 10.0.52 gestern installiert und mich an den Beispiel entlanggehangelt.

Ich möchte gerne eine kleine TCP-Verbindung aufbauen, über die nur Textnachrichten ausgetauscht werden sollen. Diese sollen dann in einer späteren Version noch interpretiert werden. Aber ich komme erst garnicht so weit, dass Nachrichten ausgetauscht werden können.

Der Server lässt sich ohne Probleme starten. Aber sobald der Client versucht zu connecten, stürtzt das Programm ab und ich habe eine Systemlast von 100%.

Am besten poste ich auch mal meinen Code... vielleicht hilft das ja!?

Server: die execute-Methode
Delphi-Quellcode:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
var
    command: String;
    connected: Boolean;

begin

  AContext.Connection.IOHandler.WriteLn('Hello');
  connected:= true;
  while connected do begin
    try
      command:= AContext.Connection.IOHandler.ReadLn;
      AContext.Connection.IOHandler.WriteLn('>>'+command);
      Label5.Caption:= command;
      if (ansiUpperCase(command) = 'BYE'or (ansiUpperCase(command) = 'QUIT'then begin
        AContext.Connection.Disconnect;
        connected:= false;
      end{ if (ansiUpperCase(line) = 'BYE') or (ansiUpperCase(line) = 'QUIT') }
    except
      connected:= false;
    end{ try/except }
  end{ do while connected }

  SleepEx(1, True);

end;


Die Methode soll also einfach nur die vom Client geschickte Nachricht im Label anzeigen und an den Client zurückschicken. Mehr (erstmal) nicht.

Der Client-Code sieht wie folgt aus:
Delphi-Quellcode:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
procedure TForm1.verbinde;
var text: String;
begin


  //IdTCPClient1.Host:= '192.168.1.3';
  //IdTCPClient1.Port:= 6666;

  try
    IdTCPClient1.Connect('127.0.0.1'6666);
  except
  on E : Exception do
    begin


      ShowMessage('Fehler: ' + E.Message);

    end;

  end{ try/except }
  try
    text:= IdTCPClient1.IOHandler.ReadLn;
    Label1.Caption:= text;
    Form1.Caption:= 'Client: verbunden mit ' + IdTCPClient1.Host;
  except
    //nix...
  end{ try/except }


end;



Wenn ich diese Methode aufrufe, steigt die Prozessorlast auf 100% und nichts geht mehr.
Beim debuggen bin ich bis zur folgenden Zeile gekommen:

Sie befindet sich in der Indy-Unit: IdWinSock2 Zeile 2937


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
Delphi-Quellcode:   
function Stub_connect (const s: TSocket; const name: PSockAddr; const namelen: Integer): Integer; stdcall;
begin
  FixupStub('connect', @connect); {Do not Localize}
  Result := connect(s, name, namelen); //bei der Ausführung dieser Zeile stürtzt das Prgramm ab!!!
end;



Hab ich da jetzt was falsch gemacht, oder ist das vielleicht nen Bug der Version, hab gesehen, dass es eine neuere gibt. Wenn ja, wie kann ich die alte Version denn deinstallieren? Oder hilft es, vielleicht doch die 9er Version zu nutzen? Falls ja, wie mache ich einen downgrade?

Wäre super, wenn mir jemand helfen könnte!

Vielen Dank im Voraus!

Andreas

Moderiert von user profile iconjasocul: Delphi-Tags hinzugefügt


sky21 - Di 13.11.07 18:12

Ehm, ist es die Serverapplikation die abstürtzt?

also wenn ich >>while connected do begin << anschaue, dann riecht das schon sehr nach einer Endlos-Schlaufe ohne jegliche Pause, was aus meiner Sicht die 100% Last erklären würde.


Quitzlinga - Mo 26.11.07 23:26

Hallo

Ich hatte am Anfang genau dieselben Schwierigkeiten, von daher Kopf hoch und durch. Die Prozessorlast von 100% ist ganz einfach zu erklären : Du arbeitest mit Indy und Indy arbeitet mit Blocking Threads. Weiterhin hast Du in deiner Routine einige Konzeptfehler, die wahrscheinlich darauf zurückzuführen sind, das Du die Indy-Komponente noch nicht richtig verstehst, aber das giebt sich mit der Zeit, da muss man halt durch.

Die folgenden Dinge sind mir aufgefallen :


  1. Du arbeitest mit einer Schleife im Execute-Ereignis des Servers und verlässt diese erst, wenn die Verbindung getrennt wird. Das ist nicht gut, da das Execute Ereignis jedesmal ausgelöst wird, wenn der Server eine Nachricht von einem Client erhält, d.h. irgentwann wird dein Server mangels Ressourcen abstürzen. Da Du bisher nur ein paar Nachrichten verschickt hast, fällt das natürlich nicht auf.


  2. Delphi-Quelltext
    1:
    AContext.Connection.IOHandler.WriteLn('Hello');                    

    Die Begrüssungsroutine hat im Execute Ereignis des Servers nichts verloren, pack diese am besten in das OnConnect-Ereignis, so wird sie nicht dauernd ausgelöst.

  3. Wie bereits am Anfang bemerkt, Du arbeitest mit Indy und Indy arbeitet mit Blocking-Threads.

    Delphi-Quelltext
    1:
    2:
    3:
    4:
    5:
    6:
    7:
      try 
        text:= IdTCPClient1.IOHandler.ReadLn;  // Hier wartet der Prozessor
        // solange, bis er eine Nachricht vom Server erhält, notfalls bis
        // zur Ewigkeit -> darum Blocking Thread
        Label1.Caption:= text; 
        Form1.Caption:= 'Client: verbunden mit ' + IdTCPClient1.Host; 
      except

    Eine Abhilfe hier wäre z.B. das warten auf Nachrichten vom Server mittels eines Threads zu realisieren. Dieser würde das Hauptprogramm nicht belasten.Ist aber etwas komplexer.


Schau Dir am besten das Netzwerktutorial von Narses einmal an. Das behandelt diese Probleme sehr gut und giebt dir auch Beispiele an die Hand (Zwar nicht mit Indy, aber die Umstellung ist kinderleicht)

Wenn Du trotzdem Hilfestellung benötigst, dann schreib mich einfach mal an. Ich hatte dieselben Problem am Anfang auch und kann daher dein Problem sehr gut verstehen.

MfG

Quitzlinga