Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   TCP-Verbindung zu mehreren Endgeräten (https://www.delphipraxis.net/195185-tcp-verbindung-zu-mehreren-endgeraeten.html)

LokutusvB 9. Feb 2018 11:59

TCP-Verbindung zu mehreren Endgeräten
 
Moinsen,

ich habe in einem Netzwerk mehrere Geräte (Server), mit denen ich mich verbinden muß. Wird bei den Geräten ein Ereignis ausgelöst, sendet dieses Gerät einen String. Mit meinem programmierten Client kann ich diesen String auch empfangen und auswerten.

Für mein Testprogramm nutze ich Delphi XE6 und TIDTCPClient sowie TiDThreadComponent.

Ich verbinde mich mit dem Client zu einem Endgerät, setze idThreadComponent auf Active und im OnRun Ereignis der idThreadComponent führe ich ein IdTCPClient.IOHandler.ReadLn durch. Werden Daten gelesen, kann ich sie verarbeiten.

Soweit klappt alles wunderbar. Nun allerdings kommt das Problem. Ich habe fortan eine variable Anzahl von Endgeräten. Ich habe noch keine brauchbare Lösung finden können, wie ich mit vorgegebenen Mitteln von TCPClient und ThreadKomponent mich mit den Geräten verbinden kann und dann Daten von jedem Endgerät empfangen kann. Führe ich in der Run-Methode der ThreadKomponent ein ReadLn aus, wartet die Methode an der Stelle, bis das entsprechende Endgerät Daten liefert. Daten von anderen Endgeräten können in der Zeit nicht gelesen werden. Kann ich die Problematik überhaupt mit diesen beiden Indy-Komponenten lösen? wenn ja, wie ist der Ansatz?

Oder geht das nur über WindowsSockets und für jede Verbindung einen Thread starten der ständig ein WSAREcv ausführt?

himitsu 9. Feb 2018 12:07

AW: TCP-Verbindung zu mehreren Endgeräten
 
Ein Client = ein Server gleichzeitig (oder mehrere nacheinander/abwechselnd)

mehrere Clients = mehrere Server


Also egal welche Kompnenten zu verwendets:
* so lange das Lesen blockierend ist, kannst du mit einem Thread nicht mehreres gleichzeitig verarbeiten.
* also pro Server eine Client-Komponente
** haben die Klientomponenten ein OnReciveEreignis brauchst du nicht unbedingt thrads
** ansonsten auch pro Komponente ein Thread, bzw. für jeden Thread seine eigene Client-Komponente

LokutusvB 19. Feb 2018 14:39

AW: TCP-Verbindung zu mehreren Endgeräten
 
Hi himitsu,

danke für deine klärenden Worte. Ich bin ein großes Stück weiter gekommen, bin mir aber nicht sicher, ob diese Lösung "sauber" und fehlerfrei Seitens Delphi Threads ist.

In meiner Hauptform habe ich ein type tcpDataClients als Record angelegt:

Delphi-Quellcode:
tcpDataClients = record
 recIndex: Integer;
 tsC: TidTCPClient;
 ...
end;
Hier werden unter anderem der Indy-Client und der Index pro Server, mit dem ich mich verbinden muß, abgelegt. Da das ganze variabel gehalten werden muß, habe ich ein Array des Records vereinbart und lese in FormCreat aus einer Ini-Datei die IP-Serveradressen ein und erzeuge die Indy-Clients. Anschließend werden die Verbindungen hergestellt.

Jetzt folgt der Teil, in dem ich mir nicht sicher bin, ob das ausfallsicher ist.

In einer Thread-Klasse übergebe ich im Konstruktor eine Variable an eine als private deklarierte Variable der Thread-Klasse. In jedem anderen Beispiel im Netz, das ich während meiner Suche gefunden habe, wird immer mit einem Pointer gearbeitet (wahrscheinlich da nur eine Variable genutzt wird).

Delphi-Quellcode:
Constructor TT_Lesen.Create;
begin
  Inherited Create(False);
  tcpRecIndex := Variable;
end;
Nun kann der Datenabruf der einzelnen Indy-Clients beginnen.

Delphi-Quellcode:
procedure TF_Main.Start;
var
  ii: Integer;
begin
  for ii := 0 to Length(tcpCls) - 1 do begin
    tcpCls[ii].recIndex := ii;
    tcpCls[ii].Lesen_Thread := TT_Lesen.Create(tcpCls[ii].recIndex);
    tcpCls[ii].Lesen_Thread.Priority := tpNormal;
    tcpCls[ii].Lesen_Thread.Resume();  
  end;
end;
Diese ist noch ganz einfach gehalten, ohne Kontrolle ob ein Thread bereits aktiv ist. Darum geht es mir aber auch nicht, sondern die Variable, die übergeben wird. Der Variable recIndex wird der Wert der Schleifenvariable zugewiesen und dem Thread übergeben. Im Thread wird diese tcpRecIndex vergeben und im Thread kann so dank dem Index das richtige Array Record Element angesprochen werden. Wie z.B.
Delphi-Quellcode:
txt := Trim(F_Main.tcpCls[tcpRecIndex].tsC.IOHandler.ReadLn());

Ist diese Lösung fehleranfällig oder kann man das in die Praxis umsetzen? Oder ist es besser, wenn ich direkt den Record an den Thread übergebe?


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