Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients (https://www.delphipraxis.net/170699-indy9-beispiel-basicclientserver-server-sendet-nachricht-alle-clients.html)

Kostas 29. Sep 2012 10:00

indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Hallo Zusammen,


Ich schaue mir gerade das aus Indy9 das Beispiel BasicClientServer an.
Für mein Vorhaben ist das genau was ich brauche. Allerdings benötige ich noch eine Möglichkeit
eine Nachricht an alle angemeldete Clients zu versenden.

Grundsätzlich geht das senden an alle Clients vom Server aus:

Code:
procedure TfrmMain.btn1Click(Sender: TObject);
var ClientList: TList;
    i:Integer;
begin
  ClientList := IdTCPServer.Threads.LockList;
  for i := 0 to ClientList.Count-1 do
    TIdPeerThread(ClientList.Items[i]).Connection.WriteLn('Nachricht an Alle');
  IdTCPServer.Threads.UnlockList;
end;
Doch leider wird der Client nicht getriggert.
Also muss der Client in einem Thead ReadLn durchführen um die Messages von Server zu bekommen.
Thread deshalb weil ansonsten der Main Thread blockieren würde.

Eine Alternative wäre auf jeder Seite einen Client und ein Server zu implementieren. Doch das halte
nur bei bestimmten Anwendungen für Sinnvoll.

Ich frage mich an dieser Stelle warum der Client eigentlich kein Event hat OnReceiveData hat?
Oder gibt es doch eine Möglichkeit dass der Client getriggert wird wenn der Server ihn Daten gesendet hat?

Gruß Kostas

nuclearping 29. Sep 2012 16:47

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Ich würde dir raten, Indy 10 zu verwenden. Indy 9 ist kein Standard mehr.

Bezüglich deines Problems liegst du richtig. Es gibt keinen "OnExecute"- / "OnDataReceived"-Event für TCP-Clients, da das ebenso nicht dem Standard entspricht. Der Client holt sich seine Daten immer vom Server, nicht umgekehrt.

Auch wenn es einen solchen Event gäbe wäre die Implementierung die gleiche: Der Client müsste mit IOHandler.IsInputBufferEmpty beim Server anfragen, ob Daten für ihn im Puffer liegen und sich diese dann abholen. Denn selbst wenn der Server an den Client schickt, geht das nicht durch die Leitung, bis der Client danach fragt.

Kostas 29. Sep 2012 19:35

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Zitat:

Zitat von nuclearping (Beitrag 1184973)
... Denn selbst wenn der Server an den Client schickt, geht das nicht durch die Leitung, bis der Client danach fragt.

oh, das ist eine sehr wichige Info! Dann ist es auch verständlich warum es kein Event gibt.

Besten Dank und eine schöne Zeit.
Gruß Kostas

sx2008 29. Sep 2012 21:52

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Zitat:

Zitat von nuclearping (Beitrag 1184973)
Es gibt keinen "OnExecute"- / "OnDataReceived"-Event für TCP-Clients, da das ebenso nicht dem Standard entspricht. Der Client holt sich seine Daten immer vom Server, nicht umgekehrt.

Das ist so nicht ganz richtig.
Sobald Client und Server verbunden sind, gibt es keinen Unterschied mehr zwischen den beiden Endpunkten.
TCP/IP verbindet die Beiden wie mit zwei Röhren in jeweils eine Richtung.
Beide Partner können jederzeit Daten in die wegführende Röhre schieben.
Beim Empfänger landen diese Daten zunächst in einem FIFO.
Die WinSock API bietet prinzipell die Möglichkeit über bestimmte Events (z.B Eintreffen neuer Daten) informiert zu werden (WSAEventSelect()).
Das funktioniert unabhängig davon ob es sich um einen Server oder Client handelt.
Ob Indy das benützt müsste man nachforschen.

Kostas 29. Sep 2012 22:16

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Danke für die Info.

Was mich gerade masiv beschäftigt, wenn der Client keinen Event bekommen sollte dass eben Daten anstehen, würde das bedeuten dass IdTCPClient1.IOHandler.Capture(lboxResults.Items); eine Anfrage zum Server senden
würde. Ich habe schon Beispiele gesehen die innerhalb eines Threads in einer Endlosschleife permanent

Code:
if not IdTCPClient1.IOHandler.InputBufferIsEmpty
then IdTCPClient1.IOHandler.ReadString()
ausführen. Damit hätte man permanent Datenverkehr zum Server.
Das kann ich mir nicht vorstellen dass das so sein soll.

Gruß Kostas

nuclearping 29. Sep 2012 22:22

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Im Prinzip ist so eine Endlosschleife richtig, bzw. eine Möglichkeit, Daten abzufragen.

Diese Schleife würde dann aber, ohne getrennte Verarbeitung, wohl ALLE Daten der Kommunikation zw. Client und Server abfangen, also auch die Antworten, die du als Request rausschickst, was einem ziemlich viele Falten auf die Stirn zaubern kann.

Alternativ, statt die Anfragen vom Server aus direkt zu senden, kannst du im Server für jeden Client eine Message-Queue (TIdThreadSafeList) anlegen, in die du die Nachrichten für den jeweiligen Client ablegst. Der Client schickt dann periodisch eine Anfrage á la "Hast du neue Nachrichten?" und der Server antwortet mit der Anzahl der Nachrichten, gefolgt von den Nachrichten selber.

Das wäre die sauberere Vorgehensweise.

Kostas 29. Sep 2012 22:34

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Hallo.

Was mir hierbei nicht gefehlt ist, mit einem Beispiel erklärt.
Angenommen ich habe eine Telefonieanwendung(CTI). Der Server ist mit der Telefonanlage verbunden,
und alle Nebenstellen verbinden sich mit dem Server. Der Client sendet ein Kommando, wähle die Nr.
Der Server führ das aus. Jetzt kommt für die Nebenstelle ein Anruf rein. Der Server soll aus der Datenbank
die Nr suchen und an den Client die Nummer, Firma, und Name senden. Wenn der Server den Client nicht antriggern
kann, und der Initiator nur der Client ist, würde das bedeuten dass der Client mindestens 1/Sec den Server
fragen müsste "Ruft mich irgend eine Sau an :-)" Wenn der Server Pech hat, ruft mich eine ganze Woche
keiner an. Es würde also jede Menge traffic erzeugt für nichts. Das halte ich nicht für sauber.
Dafür auf beiden Seiten ein Client und ein Server zu platzieren gefehlt mir auch nicht da ich dafür zwei Ports benutzen müsste.

Gruß Kostas

BUG 29. Sep 2012 22:47

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Zitat:

Zitat von Kostas (Beitrag 1185034)
Damit hätte man permanent Datenverkehr zum Server.
Das kann ich mir nicht vorstellen dass das so sein soll.

So ist es ja auch nicht ... lies dir nochmal den Post von sx2008 durch:
Zitat:

Zitat von sx2008 (Beitrag 1185032)
Sobald Client und Server verbunden sind, gibt es keinen Unterschied mehr zwischen den beiden Endpunkten.
TCP/IP verbindet die Beiden wie mit zwei Röhren in jeweils eine Richtung.
Beide Partner können jederzeit Daten in die wegführende Röhre schieben.
Beim Empfänger landen diese Daten zunächst in einem FIFO.

Das Problem bei der von dir genannten Lösung ist eher, dass da ein Thread umgebremst in einer Schleife rumfährt (aktives Warten).
Da ist die Frage, ob Indy blockierende Leseoperationen kann ... vermutlich schon.

Der Vorschlag von nuclearping ist nicht so gut:
Zitat:

Zitat von nuclearping (Beitrag 1185036)
Der Client schickt dann periodisch eine Anfrage á la "Hast du neue Nachrichten?" und der Server antwortet mit der Anzahl der Nachrichten, gefolgt von den Nachrichten selber

Diese saubere Lösung schickt immer wieder Anfragen an den Server (Polling), ohne das der was zu sagen hat ... im schlechtesten Fall verbrezelst du haufenweise Bandbreite um letztlich keine einzige Nachricht zu bekommen.
Der JavaScript-Gemeinde, die dank HTTP nur solche Protokolle nutzen konnte, wurde mittlerweile mit Websockets geholfen.
Und was können die? Im Grunde das gleiche wie TCP (noch ein bisschen Glitzer drauf).

Wenn also deine Nachricht vom Server kommt, dann sollte der diese ungefragt zu deinen Clienten schieben können => Push.

Kostas 29. Sep 2012 22:56

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Hallo,

jetzt wäre interessant zu wissen wie das mit Indy geht.
Wenn IdTCPClient kein Event dafür kennt. Möglicherweise gibt es Methoden oder irgendeine Technologie
die dafür genutzt werden kann.

Gruß Kostas

nuclearping 29. Sep 2012 23:15

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
 
Zitat:

Zitat von sx2008 (Beitrag 1185032)
Das ist so nicht ganz richtig.
[...]
Die WinSock API bietet prinzipell die Möglichkeit über bestimmte Events (z.B Eintreffen neuer Daten) informiert zu werden (WSAEventSelect()).
[...]
Ob Indy das benützt müsste man nachforschen.

Ok, das wusste ich nicht. Bei Indy ist es jedenfalls so, dass die Daten erst über die Leitung gehen, wenn der Read-Request vom Client kommt. Zumindest habe ich das hier beim Debuggen festgestellt, dass der Breakpoint im Server erst dann ausgelöst wird, wenn im Client IOHandler.ReadXYZ ausgeführt wird.

Zitat:

Zitat von BUG (Beitrag 1185040)
Diese saubere Lösung schickt immer wieder Anfragen an den Server (Polling), ohne das der was zu sagen hat ... im schlechtesten Fall verbrezelst du haufenweise Bandbreite um letztlich keine einzige Nachricht zu bekommen.

Ok, da hast du natürlich recht. :stupid:

Würde mich aber auch interessieren, wie das Pushen mit Indy funktioniert, da ich momentan ja an einem ähnlichen Problem sitze und das mit der Polling-Methode gelöst habe, was auch sauber funktioniert. Und da in meinem Fall ohnehin immer mit Traffic zu rechnen ist, während der Server läuft, ist das nicht problematisch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:52 Uhr.
Seite 1 von 2  1 2      

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