AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients
Thema durchsuchen
Ansicht
Themen-Optionen

indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

Ein Thema von Kostas · begonnen am 29. Sep 2012 · letzter Beitrag vom 1. Okt 2012
Antwort Antwort
Seite 1 von 2  1 2      
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 11:00
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
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 17:47
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.
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 20:35
... 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
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#4

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 22:52
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.
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 23:16
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
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 23:22
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.

Geändert von nuclearping (29. Sep 2012 um 23:26 Uhr)
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 23:34
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
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#8

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 23:47
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:
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:
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.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.099 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 29. Sep 2012, 23:56
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
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

AW: indy9 Beispiel BasicClientServer Server sendet Nachricht an alle Clients

  Alt 30. Sep 2012, 00:15
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.

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.

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.

Geändert von nuclearping (30. Sep 2012 um 00:18 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 15:48 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