AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi schnelle Server Client Verbindung ohne Verluste
Thema durchsuchen
Ansicht
Themen-Optionen

schnelle Server Client Verbindung ohne Verluste

Ein Thema von AJ_Oldendorf · begonnen am 28. Mär 2025 · letzter Beitrag vom 23. Apr 2025
Antwort Antwort
Benutzerbild von Sinspin
Sinspin

Registriert seit: 15. Sep 2008
Ort: Dubai
767 Beiträge
 
Delphi 10.3 Rio
 
#1

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 10:23
Ich habe mit Indy das letzte mal vor mehr als 10 Jahren gearbeitet. Keine Ahnung ob die jetzt Event basierten Datenempfang haben. (NSoftware macht das sehr schön)
Ich hatte mir das selber geschrieben. Also einen Thread der nichts anderes gemacht hat als immer wieder zu fragen ob was im Eingangspuffer ist, das in einen Zwischenpuffer geschrieben und den immer wieder untersucht bis darin ein vollständiger Datenblock gefunden wurde.
Der Datenblock wurde dann extrahiert und ein Flag gesetzt an dem ein anderer Thread erkannt hat das es was zu tuen gibt.
Kam da mal Müll dazwischen, also ein Datenblock kam nicht vollständig durch, musste der später nochmal angefragt werden.
Wobei ich das mit IP Works jetzt nicht wirklich anders mache. Es läuft nur einfach schön flüssig.

Aber eigentlich sollte es auch mit ReadLn gehen. Es sei denn beim Sender geht das "Ln" nicht raus. Dann wartest du bis zum Timeout für das aktuelle Paket und die dahinter türmen sich bis der interne Puffer voll ist.

Zeig mal deine komplette Config für das Init vom Client. Nicht das nur in der Config was nicht zu dir passt.


NSoftware : IP Works / IP Works SSL.
Stefan
Nur die Besten sterben jung
A constant is a constant until it change.
  Mit Zitat antworten Zitat
Papaschlumpf73

Registriert seit: 3. Mär 2014
Ort: Berlin
469 Beiträge
 
Delphi 12 Athens
 
#2

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 10:30
Von IPWorks gibts auch eine kostenlos nutzbare (leider auch etwas eingeschränkte) Delphi-Edition über GetIt.
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
489 Beiträge
 
Delphi 12 Athens
 
#3

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 10:50
NSoftware : IP Works / IP Works SSL muss ich mir mal angucken, auch was es da über GetIt gibt.

Aktuell sieht es so aus:

Server:

Delphi-Quellcode:
IdTCPServer.DefaultPort := PipePort;
IdTCPServer.OnConnect := IdTCPServerConnected;
IdTCPServer.OnDisconnect := IdTCPServerDisconnected;
IdTCPServer.OnException := IdTCPServerException;
IdTCPServer.OnExecute := IdTCPServerExecute;
IdTCPServer.Active := True;

procedure IdTCPServerExecute(AContext: TIdContext);
begin
  if IdTCPServer.Active then
  begin
    AContext.Connection.IOHandler.CheckForDataOnSource(10);

    if not AContext.Connection.IOHandler.InputBufferIsEmpty then
    begin
      InData := AContext.Connection.IOHandler.ReadLn('#~#*' + EOL, 100, -1, IndyTextEncoding_UTF8);
      if InData <> 'then
      begin
        //mach irgendwas
      end;
  end;
end;
Im IdTCPServerConnected, IdTCPServerDisconnected und IdTCPServerException sind nur Protokollierungen. Die sind aber auch nicht zu sehen, kommen also nicht (außer natürlich das 1x Connect, da ein Client sich verbindet).

Client:

Delphi-Quellcode:
IdTCPClient1.OnConnected := IdTCPClientConnected;
IdTCPClient1.OnDisconnected := IdTCPClientDisconnected;
IdTCPClient1.OnStatus := IdTCPClientStatus;
IdTCPClient1.Host := aServerIP;
IdTCPClient1.Port := aPort;

procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
    IdTCPClient1.IOHandler.CheckForDataOnSource(10);

    if not IdTCPClient1.IOHandler.InputBufferIsEmpty then
    begin
      InData := IdTCPClient1.IOHandler.ReadLn('#~#*' + EOL, 100, -1, IndyTextEncoding_UTF8);

      if InData <> 'then
      begin
        //mach irgendwas
      end;
  end;
end;
Im IdTCPClientConnected, IdTCPClientDisconnected und IdTCPClientStatus sind nur Protokollierungen. Die sind aber auch nicht zu sehen, kommen also nicht (außer natürlich das 1x Connect, da der Client sich verbindet).

Natürlich ist noch mehr Quelltext drum herum aber das ist die Implementierung von Server und Client.
Wie gesagt, der Server schickt im Durchschnitt 60 Datensätze (unterschiedlicher Inhalt) pro Sekunde mit einer Länge von 13 Byte bis max 61000 Byte
  Mit Zitat antworten Zitat
Papaschlumpf73

Registriert seit: 3. Mär 2014
Ort: Berlin
469 Beiträge
 
Delphi 12 Athens
 
#4

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 11:04
Stefan meinte wohl das hier im .Execute

Delphi-Quellcode:
      if InData <> 'then
      begin
        //mach irgendwas
      end;
Hier sollten die Daten nur weggespeichert und ggf. durch einen anderen Thread verarbeitet werden. Sonst kann hier ein Flaschenhals entstehen.
  Mit Zitat antworten Zitat
Benutzerbild von fisipjm
fisipjm

Registriert seit: 28. Okt 2013
402 Beiträge
 
Delphi 13 Florence
 
#5

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 11:13
Darf ich dazu mal eine "blöde" Frage stellen?
Was für Daten möchtest du denn Übertragen? Was bedeutet denn Datensätze?
Ich würde es mir an deiner Stelle nicht so kompliziert machen. Um Daten von einem Server zu einem Client zu Übertragen schlägt man sich normalerweise nicht mehr mit TCP und dem ganzen geraffel herum.

Best-Practice wäre aus meiner Sicht folgendes:
1.) Auf der Server Seite setzt du dir einen kleinen Webserver auf. Minimale Lösung z.B. Horse. (Bei der Gelegenheit kann man sich auch gleich mal mit Boss auseinandersetzen, vom Grundprinzip sowas wie der Packagemanager nvm nur für Delphi). Wenn du dann auch noch jwt als middleware nutzt, hast du auch gleich noch etwas das sich brauchbar um die Verschlüsslung deiner Kommunikation kümmert.
2.) Deine Datensätze Packst du in Klassen. Wenn du mehrere Datensätze auf einmal Schicken willst packste dir die Klassen in ein Tarray<MyClass> und lässt es danach mit TJSON.ObjectToJSONStr serialisieren. (oder du nimmst gleich irgend ein ORM, oder, oder, oder)


Vorteile:
Aus meiner Sicht kommst du damit locker an die von dir angesprochenen ca. 3,5 MB pro Sekunde (61000Byte x 60(Pakete/s) / 1024 / 1024) hin.
Du brauchst dich nicht mehr um die Reihenfolge kümmern.
Du brauchst dich nicht mehr um das ganzen TCP/IP Connection Zeug kümmern.

Nachteil:
Overhead des HTTP layers, aber wie gesagt, deine Datenrate solltest du damit dicke schaffen.

Ansonsten kannst du die auch mal Websocket zu diesem Thema anschauen. Das ist aber eine ganze Ecke komplizierter.

vG
PJM
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
489 Beiträge
 
Delphi 12 Athens
 
#6

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 12:10
Zitat:
Stefan meinte wohl das hier im .Execute
Also ich habe jetzt jeweils nach dem Senden und Empfang keiner weiteren Aktivitäten mehr, der Client hängt trotzdem hinterher (wesentlich!).

Ein Versuch wäre noch, beides mal wirklich in kleine separate Threads auszulagern, jetzt ist noch ein wenig Overhead drum herum was vielleicht ein Problem sein könnte. Ich werde dazu berichten.

Zitat:
Darf ich dazu mal eine "blöde" Frage stellen?
Also im Endeffekt sind das codierte Strings die dann irgendwelche Commands enthalten und irgendwelche Werte / Signale.

Zitat:
Ich würde es mir an deiner Stelle nicht so kompliziert machen
Naja, das TCPIP Connect/Disconnect geht ja prinzipiell. Dein Vorschlag mir Server und irgendeiner Middleware und JSON etc hört sich aus meiner Sicht erstmal kompliziert an, da davon bei uns aktuell 0 existiert und man sich damit von Grund auf neu beschäftigen müsste. Das andere ist ja da und muss nur implementiert werden. Nicht falsch verstehen, ich bin gerne offen für eine andere Lösung aber wenn dazu erst noch dies und das eingerichtet/gehostet werden muss, ist das nicht praktikabel in unserem Fall. Es soll am Ende nur von einer Windows Anwendung zu einer anderen Windows Anwendung Daten übertragen werden. Diese läuft jeweils auf einem anderen Rechner. Server schickt dem Client was, Client kann dem Server antworten. Das ist das Grundprinzip

Zitat:
Vorteil wäre das man damit das dann auf Geschwindigkeit optimieren kann, wo TCP systembedingt langsamer sein muss.
Genau das habe ich auch schon versucht mit UDP und habe eine Sequenz eingebaut. Wenn man diese mit einbaut, ist es im Prinzip wieder so schnell/langsam wie TCP, da der Client jedes Telegram beantworten muss (damit der Server feststellt, dass es angekommen ist) und der Server muss es wiederholen, falls es vom Client nicht quittiert wurde. Und ohne Sequenz kann man UDP vergessen, da Telegramme verloren gehen können oder sich überholen. Fällt dahe raus

Geändert von AJ_Oldendorf (28. Mär 2025 um 12:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.243 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 13:58
Genau das habe ich auch schon versucht mit UDP und habe eine Sequenz eingebaut. Wenn man diese mit einbaut, ist es im Prinzip wieder so schnell/langsam wie TCP, da der Client jedes Telegram beantworten muss (damit der Server feststellt, dass es angekommen ist) und der Server muss es wiederholen, falls es vom Client nicht quittiert wurde. Und ohne Sequenz kann man UDP vergessen, da Telegramme verloren gehen können oder sich überholen. Fällt dahe raus
Wenn der Server ein Packet bestätigt haben will bevor er das nächste abschickt bringt UDP nix.
Der Server muss dann mehrere Packete auf die Reihe schicken und wenn ein Packet nach Zeit x nicht bestätigt wird nochmal senden.
Oder auch der Client bestätigt die Packete "im Block", oder....
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.018 Beiträge
 
Delphi 2009 Professional
 
#8

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 16:47
Server schickt dem Client was, Client kann dem Server antworten. Das ist das Grundprinzip
Das ist ein Protokoll das nicht so ganz zu HTTP (siehe Vorschlag weiter vorher) passt. Der Client muss hier nun warten, bis Daten vom Server kommen, diese verarbeiten, und dann wieder warten. (und eventuell eine Antwort zurücksenden).

Dieses Kommunikationsmuster habe ich mit Indy mal in in einem kleinen Demoprogramm als 'umgekehrte request-response' (Anfrage/Antwort) umgesetzt.

https://mikejustin.wordpress.com/202...ocket-library/, Code ist auf https://github.com/michaelJustin/ind...equestResponse

Die Oberfläche erlaubt wahlweise, dass der Client eine Anfrage an den Server sendet, oder umgekehrt, der Server eine Anfrage an den Client sendet.

Es fehlt zwar etwas Fehlerbehandlung - zum Beispiel Prüfung auf ReadLnTimeout nach Readln - aber es zeigt, dass auch der Server die erste(n) Nachricht(en) senden kann, nachdem die Verbindung hergestellt ist.

Der clientseitige Code läuft in einem Thread und sein Betriebsmodus wird durch ein Flag gesteuert. Entweder wird ein Request gesendet und dann auf die Antwort gewartet, oder auf einen Request gewartet und eine Antwort gesendet.

Delphi-Quellcode:
while not Terminated do
begin
  if Send then
  begin
    // send request to server and receive response
    Send := False;
    Request := 'REQ:' + FClientRequestHolder.Text;
    TCPClient.IOHandler.WriteLn(Request);
    repeat
      Response := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8);
    until Response <> '';
    LogInMainThread(Request, Response);
  end
  else
  begin
    // receive request from server and send response
    Request := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8);
    if StartsStr('REQ:', Request) then
    begin
      Response := 'from client ' + ReverseString(Request);
      TCPClient.IOHandler.WriteLn(Response);
    end;
  end;
end;
An diesem Beispiel fällt die Abwesenheit von CheckForDataOnSource auf. Dieses wird nicht benötigt, da ReadLn solange wartet, bis eine Zeile aus dem Socket gelesen wurde, oder es zu einem Timeout kommt.
Michael Justin

Geändert von mjustin (28. Mär 2025 um 17:20 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sinspin
Sinspin

Registriert seit: 15. Sep 2008
Ort: Dubai
767 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 12:16
Nen extra Server aufsetzen ist wie Kanonen und Spatzen. Direkt TCPIP is schon die smarteste Lösung für so kleine Sachen.

Aktuell sieht es so aus:

Server:
Delphi-Quellcode:
IdTCPServer.DefaultPort := PipePort;
IdTCPServer.OnConnect := IdTCPServerConnected;
IdTCPServer.OnDisconnect := IdTCPServerDisconnected;
IdTCPServer.OnException := IdTCPServerException;
IdTCPServer.OnExecute := IdTCPServerExecute;
IdTCPServer.Active := True;
<...>
Ich hatte eher gemeint was für Einstellungen für Timeouts, connection handing (keep alive, etc)
Du nimmst die default Einstellungen der Komponente?
Solchen Problemen ist immer schwer beizukommen. Indy Sourcen sind aber mit dabei. Da mal versucht duchzusteppen?
Delphi-Quellcode:
IdTCPClient1.IOHandler.CheckForDataOnSource(10);
<...>
InData := IdTCPClient1.IOHandler.ReadLn('#~#*' + EOL, 100, -1, IndyTextEncoding_UTF8);
<...>
Ich habe jetzt die Quelltexte nicht da um zu prüfen was ReadLn macht, aber eventuell ist die Kombination aus "CheckForDataOnSource" und "ReadLn" das Problem. Was passiert wenn du "CheckForDataOnSource" weglässt?
Stefan
Nur die Besten sterben jung
A constant is a constant until it change.
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
489 Beiträge
 
Delphi 12 Athens
 
#10

AW: schnelle Server Client Verbindung ohne Verluste

  Alt 28. Mär 2025, 13:19
Zitat:
Ich hatte eher gemeint was für Einstellungen für Timeouts, connection handing (keep alive, etc)
Ich habe gar keine Timeouts oder keep alive gesetzt.
Die Einstellungen der Komponenten sind im Anhang.

Zitat:
Was passiert wenn du "CheckForDataOnSource" weglässt?
Das könnte ich generell mal beim Client versuchen.

Beim Server wurde es im "IdTCPServerExecute" gebraucht, da sonst die CPU Last auf knapp 6% hoch ging. Der Tipp kam von Jaenicke hier https://www.delphipraxis.net/1546974-post25.html
Angehängte Grafiken
Dateityp: png 2025.03.28-13_14_33-001.png (23,6 KB, 11x aufgerufen)
Dateityp: png 2025.03.28-13_14_50-001.png (22,4 KB, 9x aufgerufen)
Dateityp: png 2025.03.28-13_15_20-001.png (28,5 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


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 19:40 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