AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???
Thema durchsuchen
Ansicht
Themen-Optionen

Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

Ein Thema von romber · begonnen am 20. Apr 2014 · letzter Beitrag vom 21. Apr 2014
Antwort Antwort
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.164 Beiträge
 
Delphi 10 Seattle Professional
 
#1

Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

  Alt 20. Apr 2014, 14:55
Hallo!
Frohe Ostern und schöne Feiertage!

Ein Server (der selber ein Webservice-Client ist) empfängt pro Minute mehrere Hundert einzelne String-Datensätze, die er dann an alle verbundenen Clients weiterleitet. Die Übertragung geschieht mittels TIdTCPServer/TIdTCPClient. Bis jetzt habe ich die Daten auch als Strings an die Clients geschickt. Auf der Clientseite wird jeder empfangene Datensatz in einen XML-Reader geladen. Der XML-Reader benutzt dafür eine Funktion namens LoadFromXML, die nichts anderes macht, als die Daten in ein Stream zu laden, um dann mittels LoadFromStream an den Reader zu übergeben. Jetzt überlege ich mir, ob es nicht besser wäre, die Datensätze direkt als Streams zu übertragen. Dazu hätte ich einige Fragen an die erfahrenen Experten:

1. Ist die Datenübertragung mittels Streams grundsätzlich schneller oder langsammer als die mit Strings? Macht es überhaupt Sinn, auf Streams umzubauen?
2. Wie schon erwähnt, müssen permanent mehrere Hundert einzelne Datensätze pro Minute hintereinander übertragen werden. Ist die Übertragung mittels Streams überhaupt dafür geeignet?
3. Im Fall von Strings muss ich jeden zu übertragenen String mit einer eindeutigen Zeichenkombination beenden, damit der Client die "zusammengewachsene" Datenpakete auseinander halten kann. Muss ich irgendwas in der Art auch für Streams anwenden?
4. In Foren wird es viel diskutiert über die Übertragung von Daten in Records (auch mittels Streams). Welche Vorteile könnten Records in meinem Fall haben?

Im Voraus vielen Dank!

Geändert von romber (20. Apr 2014 um 15:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

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

AW: Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

  Alt 20. Apr 2014, 18:57
... muss ich jeden zu übertragenen String mit einer eindeutigen Zeichenkombination beenden, damit der Client die "zusammengewachsene" Datenpakete auseinander halten kann
Das ist die wichtigste Frage bei TCP überhaupt.
Zunächst einmal ist TCP streambasiert, d.h. man muss sich das so vorstellen wie eine Röhre aus der immer wieder Kugeln (Bytes) herausfallen.
(es gibt noch eine 2. Röhre in Gegenrichtung)
Wieviele Kugeln direkt nacheinander rausfallen lässt sich nicht vorhersehen, denn das hängt von vielen Faktoren des Netzwerks und des IP-Stacks ab.
Daher ist es unbedingt notwendig einzelne Nachrichten mit irgendeinem Verfahren zu trennen.
Gebräuchlich sind Verfahren die einzelne Nachrichten durch ein eindeutiges Zeichen (meist Carriage Return) trennen oder vor jeder Nachricht die Anzahl der folgenden Bytes übermitteln.

Ob man Nachrichten als Strings versendet oder eine TStream-Klasse einsetzt ist nicht so wichtig.
Wichtig ist dass man ein gutes Protokoll definiert und dass der Empfänger damit umgehen kann nur Bruchstücke einer Nachricht zu empfangen und daraus die ursprünglichen Nachrichten wieder herstellen kann.
fork me on Github
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.004 Beiträge
 
Delphi 2009 Professional
 
#3

AW: Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

  Alt 20. Apr 2014, 20:19
1. Ist die Datenübertragung mittels Streams grundsätzlich schneller oder langsammer als die mit Strings? Macht es überhaupt Sinn, auf Streams umzubauen?
Wenn man sich auf eine stringbasierte Übertragung festlegt, werden binäre Daten noermalerweise erst in einen String übersetzt, damit dieser dann mit einem eindeutigen Terminator abgeschlossen werden kann. Durch die Kodierung steigt der Platzbedarf des Datenstroms um 33–36 % (Base64, http://de.wikipedia.org/wiki/Base64).

In diesem Fall ist es vorteilhafter einen Stream zu senden: zum einen spart es Bandbreite, und es entfällt die Base64 Konvertierung auf Server und Client.

2. Wie schon erwähnt, müssen permanent mehrere Hundert einzelne Datensätze pro Minute hintereinander übertragen werden. Ist die Übertragung mittels Streams überhaupt dafür geeignet?
Begrenzt wird die Leistung durch die freien Hardwareresourcen und das Netzwerk. Es kommt auf den Umfang der Daten an, eine Nachrichtenfrequenz von mehreren pro Sekunde ist völlig harmlos (auf einem Kern schaffe ich aktuell von einem Delphi TCP Client bis zu 40.000 Nachrichten die an einen auf Java basierenden Server gesendet und von diesem an den Client zurückgesendet werden).

3. Im Fall von Strings muss ich jeden zu übertragenen String mit einer eindeutigen Zeichenkombination beenden, damit der Client die "zusammengewachsene" Datenpakete auseinander halten kann. Muss ich irgendwas in der Art auch für Streams anwenden?
Übertragung mittels Streams überhaupt dafür geeignet?
Da Streams auch jedes denkbare Endekennzeichen enthalten können, geht es nur umgekhert - mit einer Übermittlung der Länge vor den Bytes des Streams. Indy's TIdTCPClient.IOHandler unterstützt aber das Senden / Empangen von Streams mit einer automatisch vorangestellten Längenangabe. Damit ist nur wenig eigener Code notwendig. Wichtig ist vor allem die Freigabe des Streams nach seiner Verwendung (auf beiden Seiten).

4. In Foren wird es viel diskutiert über die Übertragung von Daten in Records (auch mittels Streams). Welche Vorteile könnten Records in meinem Fall haben?
Records funktionieren nur wenn Client und Server garantiert exakt den gleichen Recordtypen verwenden. Sobald dies nicht garantiert ist (verschiedene Server / Clientversionen gleichzeitig im Einsatz, 32/64 Bit Unterstützung...) sind andere Formate robuster.
Michael Justin
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

  Alt 20. Apr 2014, 21:33
[OT oder nicht, dürfte etwas mit dem Thema zu tun haben]

Ich hab kürzlich irgendwo aufgeschnappt, dass man mit Strings evtentuelle Probleme mit Endianness ganz umgeht - stimmt das eig. so?
Bei der ANSI (und sonstigen 1 Byte/Zeichen) Kodierung ist mir klar, dass die Daten immer in einer einzigen Reihenfolge im Speicher liegen, weil
die Anordnungsmöglichkeit bei 1 Byte eben nur 1 ist.
Gilt es aber auch für andere Kodierungen, die mehr benötigen? Wenn man z.B. 2 oder 4 Byte / Zeichen benötigt, können die ja, je nach Endianness, anders im Speicher liegen -
oder werden Strings speziell gehandhabt?

Weil das wäre dann oder auch immer (wenn nur 1 Byte/Zeichen) ein Pluspunkt für ein String-basiertes Protokoll!
Klärt micht auf!


[/OT]

@mjustin
Man muss ja nicht wirklich base64 kodieren, oder? Ich kanns mir nur dann vorstellen, wenn man Kollisionen mit Terminalzeichen & Daten vermeiden will.
Das kann man aber auch anders und viel eleganter lösen, indem man die Terminalzeichen, die so im Datensatz vorkommen, einfach escaped.
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

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

AW: Indy TCP Server/Client: Streams senden/empfangen und Unterschied zu Strings???

  Alt 21. Apr 2014, 22:50
Ich hab kürzlich irgendwo aufgeschnappt, dass man mit Strings evtentuelle Probleme mit Endianness ganz umgeht - stimmt das eig. so?
Mehr oder wenige ja, da die Reihenfolge bei Zahlencodierung in Strings üblicherweise immer Big-Endian ist.

Wenn man z.B. 2 oder 4 Byte / Zeichen benötigt, können die ja, je nach Endianness, anders im Speicher liegen
Das Problem gibt es tatsächlich, zum Beispiel bei UTF-16. Bei dem im Web gebräuchlichem UTF-8 ist das wieder kein Problem.

Das kann man aber auch anders und viel eleganter lösen, indem man die Terminalzeichen, die so im Datensatz vorkommen, einfach escaped.
Relativ günstig finde ich die Lösung mit vorangestellter Nachrichtenlänge, da man dabei schon vor Ende der Nachricht weiß, wie groß diese sein wird.


Zum richtigen Thema, habe ich das richtig verstanden:
  1. Du hast Strings, die XML enthalten.
  2. Du versendest diese Strings durch ein bestimmtes Zeichen getrennt über TCP.
  3. Dein Client-seitiger XML-Reader bekommt einen String, den er in einen Stream schreibt, um ihn dann auszulesen.
In diesem Fall: Du wirst durch das "direkte" Versenden der XML-Daten nicht viel einsparen können. Da einzige, was dir (abgesehen von der Zeit beim Kopieren) verloren geht, ist ein kleinen Potenzial zur Parallelisierung (Netzwerk-IO und der XML-Reader). Solange du XML versendest, versendest du Text/Zeichenketten. Je nach Art des Datensätzen kann eine Kodierung in XML locker 10x so groß sein. Dort liegt das eigentliche Potenzial zur Einsparung von Netzwerklast.

Geändert von BUG (21. Apr 2014 um 22:56 Uhr)
  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 14:12 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