Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy10 IdTCPServer Problem (https://www.delphipraxis.net/123800-indy10-idtcpserver-problem.html)

ASKtec 8. Nov 2008 23:43


Indy10 IdTCPServer Problem
 
Hallo zusammen,

ich habe ein Problem mit einem Indy IdTCPServer...

Der Server läuft eine gewisse Zeit (ca 1 Std) ohne Probleme. Innerhalb dieser Zeit bekommt er alle 3 min einen Nachricht, die er an die verbunden Clients (derzeit 3) übermittelt. Nur dann plötzlich steigt er aus und ich verstehe nicht warum. Die Applikation bleibt zu sehen, jedoch ist ein beenden nur noch über den Taskmanager drin und eine neue Verbindung nimmt er auch nicht mehr an...

Die Indy-Komponenten habe ich gestern erst geupdated um zu vermeiden, dass evtl. mit einem älteren Release zusammenhängt...

Hier mal ein wenig Quellcode des Servers:

Der Server wird zur Laufzeit erstellt:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  IdTCPServer1 := TIdTCPServer.Create(self);
  IdTCPServer1.OnExecute := IdTCPServer1Execute;
  IdTCPServer1.OnConnect := IdTCPServer1Connect;
  IdTCPServer1.OnDisconnect := IdTCPServer1Disconnect;

  LoadSettings;

  IDTCPServer1.Active := true;
  if IDTCPServer1.Active then
    Log.Lines.Add(TimeToStr(now) + ': Server gestartet');
end;
Dann passiert im onExecute folgendes:
Delphi-Quellcode:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var text, ip, command:string;
i:Integer;
List: TList;
begin
  text := Acontext.Connection.IOHandler.ReadLn;
  ip := Acontext.Connection.Socket.Binding.PeerIP;

  Command:= Copy(text, 1, Pos(':', text)-1);

  if Command <> 'NOOP' then
    Log.Lines.Add(TimeToStr(now) + ': ' + ip + ' ' + text);
  if Command = 'TITLE' then
    title := text;
  if Command = 'HELO' then
    text := title;

  ListView1.Clear;

  List := IdTCPServer1.Contexts.LockList;
  for i := 0 to List.Count - 1 do
    begin
    TidContext(List.Items[i]).Connection.IOHandler.WriteLn(text);
    with Listview1.Items.Add do
      caption := TIdContext(List.Items[i]).Connection.Socket.Binding.PeerIP;
   end;
  IdTCPServer1.Contexts.UnlockList;
end;
OnConnect macht nur einen Eintrag in ein Memo (Log):
Delphi-Quellcode:
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
  Log.Lines.Add('Verbindung: ' + AContext.Binding.PeerIP);
end;
und OnDisconnet;
Delphi-Quellcode:
procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
  Log.Lines.Add('Verbindungsabbruch: ' + AContext.Binding.PeerIP);
end;

Mache ich hier irgendwo einen Fehler? Der Client der die Daten schickt bleibt ständig verbunden und zeigt auch weiterhin verbunden an, obwohl er im Server nicht mehr sichtbar ist (ich schicke vom Client aus zwischendurch eine Nachricht um festzustellen ob er noch lebt)...

Wer kann mir helfen?

Vielen Dank im voraus

Andreas

omata 8. Nov 2008 23:54

Re: Indy10 IdTCPServer Problem
 
Die VCL ist nicht Threadsicher, benutze deshalb Kritische Abschnitte.

Delphi-Quellcode:
uses ..., SyncObjs;

type
  :
  private
    { Private-Deklarationen }
    FCriticalSection:TCriticalSection;
  :
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCriticalSection:=TCriticalSection.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FCriticalSection.free;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
:
begin
  :
  FCriticalSection.Enter;
  try
    ListView1.Clear;
    List := IdTCPServer1.Contexts.LockList;
    for i := 0 to List.Count - 1 do begin
      TidContext(List.Items[i]).Connection.IOHandler.WriteLn(text);
      with Listview1.Items.Add do
        caption := TIdContext(List.Items[i]).Connection.Socket.Binding.PeerIP;
    end;
    IdTCPServer1.Contexts.UnlockList;
  finally
    FCriticalSection.Leave;
  end;
end;

ASKtec 9. Nov 2008 00:20

Re: Indy10 IdTCPServer Problem
 
Hallo,

vielen Dank für die schnelle Antwort. Ich habe es gleich ein gebaut...

Nun muss ich nur mal noch ne einfach Erklärung finden, was genau diese Kritische Abschnitte sind und machen 8)

Gruß
Andreas

omata 9. Nov 2008 00:23

Re: Indy10 IdTCPServer Problem
 
klick

ASKtec 9. Nov 2008 01:01

Re: Indy10 IdTCPServer Problem
 
Danke für den Link...

Aber der Server macht immernoch das gleiche. Wobei ich diesmal auch sehen konnte dass der Server eine CPU Last von 49% hatte als nichts mehr ging...

Hat vielleicht noch jemand eine Idee??? Gibt es vielleicht eine gute Alternative zu den Indy-Komponenten die ich nutzen könnte?

Gruß und Danke
Andreas

gsh 9. Nov 2008 09:30

Re: Indy10 IdTCPServer Problem
 
hast du schon mal versucht den server zu debuggen?
also schritt für schritt durchgehen und schauen wann er hängen bleibt

ASKtec 9. Nov 2008 11:58

Re: Indy10 IdTCPServer Problem
 
Hallo gsh,

nein noch nicht wirklich. Das Problem tritt erst nach ca 45 min bis 1 Stunde auf. Ich werde nun mal jeden Schritt in ein Logfile eintragen. Vieleicht kommt dabei was zu Tage. Da er alle 3-4 Minuten Daten empfängt und diese dann an 3 Clients verteilt sind das viele Schritte die 1000 mal funktionieren und dann plötzlich nicht mehr :roll:

Ich dachte, dass vielleicht jemand die Problematik hier bekannt ist...

Ich werde nun mal das Logfile integrieren und dann mal schauen ob es neue Erkenntnisse bringt.

Gruß
Andreas

ASKtec 9. Nov 2008 14:01

Re: Indy10 IdTCPServer Problem
 
So, neue Erkenntnisse aus dem Logfile....

Hier mal zuerst die Auszüge aus dem Logfile wie es regelmäßig erscheint und auch in Ordnung ist:

Delphi-Quellcode:
09.11.2008 14:39:17: OnExecute durch: 127.0.0.1
09.11.2008 14:39:28: 192.168.100.207: NOOP:
09.11.2008 14:39:28: 192.168.100.207: CriticalSecion Enter passed
09.11.2008 14:39:28: 192.168.100.207: Contexts.LockList passed
09.11.2008 14:39:28: Schleife beginnt
09.11.2008 14:39:28: 127.0.0.1(0): WriteLN passed
09.11.2008 14:39:28: 192.168.100.207(1): WriteLN passed
09.11.2008 14:39:28: 192.168.100.65(2): WriteLN passed
09.11.2008 14:39:28: 127.0.0.1: NOOP:
09.11.2008 14:39:28: Schleife Ende
09.11.2008 14:39:28: 192.168.100.207: Contexts.UnlockList passed
09.11.2008 14:39:28: 192.168.100.207: CriticalSecion.Leave passed

Und so sieht es aus wenn es kracht:

Delphi-Quellcode:
09.11.2008 14:39:28: OnExecute durch: 192.168.100.207
09.11.2008 14:39:43: 192.168.100.65: NOOP:
09.11.2008 14:39:50: OnConnect mit: 127.0.0.1
09.11.2008 14:39:50: OnExecute durch: 127.0.0.1
09.11.2008 14:39:50: 127.0.0.1: HELO:client
09.11.2008 14:39:58: 192.168.100.207: NOOP:
Hier ist auffällig, dass in einem OnExecute-Event plötzlich ein OnConnect und ein weiteres OnExecute ausgelöst wird. Hierbei kommt die Komponente wohl ins schleudern und bleibt stecken...

Nur wie kann ich das verhindern???

Viele Grüße und Danke
Andreas

jfheins 9. Nov 2008 14:15

Re: Indy10 IdTCPServer Problem
 
Dann versuche mal, die gleiche Critical Section auch im OnConnect (und am besten auch im OnDisconnect) zu verwenden. Damit wird ausgeschlossen, dass eine Event eintritt, während ein anderes gerade behandelt wird ;)

omata 9. Nov 2008 15:08

Re: Indy10 IdTCPServer Problem
 
Dein Log-Objekt ist eine StringList, die ist auch nicht Threadsafe! Die ist mir gestern gar nicht weiter aufgefallen.

Eine andere Möglichkeit ist, wenn dein Server intern sowieso nur einmal betreten werden darf, die MaxConnection-Eigenschaft des Servers auf eins zu setzen. Das wird dann allerdings deine Verbidungsgeschwindigkeit drosseln, weil die Indys dann diesen Schutz für dich organisieren. Dies geht allerdings nur, wenn sich die Clients jedesmal an-/abmelden.

ASKtec 9. Nov 2008 15:43

Re: Indy10 IdTCPServer Problem
 
Hmm, eigentlich sollen sich mal später zwischen 20 und 30 Clients verbinden können ohne dass es Probleme gibt...

Wie benutze ich denn die gleiche CriticalSection nochmal? Einfach zu Beginn und am Ende ein Enter und ein Leave aufrufen?

@omata
Welches Log-Objekt meinst Du? Das Memo oder das Logfile das ich jetzt eingebaut habe?

Wie komme ich denn nun weiter um das ganze stabil zum laufen zu bekommen?

Danke nochmal und viele Grüße
Andreas

omata 9. Nov 2008 15:46

Re: Indy10 IdTCPServer Problem
 
Zitat:

Zitat von ASKtec
Wie benutze ich denn die gleiche CriticalSection nochmal? Einfach zu Beginn und am Ende ein Enter und ein Leave aufrufen?

ja

Zitat:

Zitat von ASKtec
@omata
Welches Log-Objekt meinst Du? Das Memo oder das Logfile das ich jetzt eingebaut habe?

Das Objekt, das "Log" heisst, das ist doch auch schon im ersten Post zu sehen.

ASKtec 9. Nov 2008 15:54

Re: Indy10 IdTCPServer Problem
 
ok, wäre es dann vielleicht sinnvoll immer zu Beginn des Serverevents die CriticalSection zu beginnen und damit die anderen Threads warten zu lassen???

Oder bringt das wieder andere Probleme?

omata 9. Nov 2008 16:06

Re: Indy10 IdTCPServer Problem
 
Ja entweder so, oder die schützt deinen Zugriff jeweils einzeln, damit nicht immer alle überall ausgesperrt werden.
Bau also einen Wrapper für das Log und schütze die Zugriffe auf dieses mit einem Kristischen Abschnitt und den Zugriff auf deine visuelle Komponente schützt du dann mit einem anderen Kritischen Abschnitt.

Win32.API 9. Nov 2008 16:58

Re: Indy10 IdTCPServer Problem
 
Zitat:

Zitat von omata
Die VCL ist nicht Threadsicher, benutze deshalb Kritische Abschnitte.

Delphi-Quellcode:
uses ..., SyncObjs;

type
  :
  private
    { Private-Deklarationen }
    FCriticalSection:TCriticalSection;
  :
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCriticalSection:=TCriticalSection.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FCriticalSection.free;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
:
begin
  :
  FCriticalSection.Enter;
  try
    ListView1.Clear;
    List := IdTCPServer1.Contexts.LockList;
    for i := 0 to List.Count - 1 do begin
      TidContext(List.Items[i]).Connection.IOHandler.WriteLn(text);
      with Listview1.Items.Add do
        caption := TIdContext(List.Items[i]).Connection.Socket.Binding.PeerIP;
    end;
    IdTCPServer1.Contexts.UnlockList;
  finally
    FCriticalSection.Leave;
  end;
end;


Ist so auch nicht richtig, du _darfst_ nur aus dem Mainthread auf Elemenate der VCL zugreifen. Das geht mittels Synchronize.

Win32.API

omata 9. Nov 2008 17:04

Re: Indy10 IdTCPServer Problem
 
Zitat:

Zitat von Win32.API
Ist so auch nicht richtig, du _darfst_ nur aus dem Mainthread auf Elemenate der VCL zugreifen. Das geht mittels Synchronize.

Und wie willst du dann an die Informationen aus AContext rankommen?

ASKtec 9. Nov 2008 19:47

Re: Indy10 IdTCPServer Problem
 
Hallo,

so wie es im Moment aussieht habe ich es nun geschafft dass es funktioniert. Ich habe für das schreiben der Logdatei eine Prozedur angelegt und dort eine eigene CriticalSection am Anfang und am Ende eingefügt.

Im OnExecute schaue ich dann erst nach dem Kommando. Dann kapsele ich beim richtigen Kommando in einer eigenen CriticalSection den weiteren Ablauf.

Zum testen habe ich eben mal einen Art Chatclient mit einem Timer, der jede Sekunde eine Zufallsnachricht an den Server schickt, programmiert und davon mal 10 Stück auf den Server losgelassen. Dabei ist nichts aus dem Ruder gelaufen.

Nun habe ich den Server da laufen wo er hin soll... in ca. 1 Stunde weiß ich dann mehr.

Gruß und Danke an alle die mir hier geholfen haben :cheers:

Andreas

Win32.API 9. Nov 2008 21:26

Re: Indy10 IdTCPServer Problem
 
Zitat:

Zitat von omata
Zitat:

Zitat von Win32.API
Ist so auch nicht richtig, du _darfst_ nur aus dem Mainthread auf Elemenate der VCL zugreifen. Das geht mittels Synchronize.

Und wie willst du dann an die Informationen aus AContext rankommen?


Wie schon gesagt: Mit Synchronize kann man eine Funktion im Kontext des Mainthreads ausfuehren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:36 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