Forum: PC-Programmierung Fragen zur Datenübertragung mit TCP oder UDP


von Thomas (Gast)


Lesenswert?

Hallo zusammen,

ich habe mal die ein oder andere Frage zur Datenübertragung mit TCP und 
UDP.

Und zwar möchte ich mir von einem Server zyklisch Daten in einem 
Intervall von z.B. 20 ms zuschicken lassen.

Der Client soll in einer Art Spielumgebung laufen.
Bei Start der Berechnung eines neuen Frames, sollen aktuelle Daten vom 
Server anliegen. Nach der Berechnung sollen ebenfalls Daten an den 
Server zurückgeschrieben werden. Danach wird das Bild gerendert und der 
Zyklus startet von vorn.

Jetzt könnte der Client dem Server bei Start des Spiels sagen, er solle 
die Daten im 10 ms Zyklus schicken damit diese auf jeden Fall bei jedem 
Frame aktuell sind.
Damit es nicht zu Verzögerungen kommt, will ich nicht bei jedem Zyklus 
eine Anfrage schicken und dann auf Antwort warten.

Jetzt frage ich mich: wenn der Client nur alle 20 ms abruft, sind dann 
zwei Datensätze im Puffer?
Oder bekommt der Server erst eine Bestätigung dass die Daten angekommen 
sind, wenn der Client die Daten ausliest?

Und wie sieht das bei UDP aus: Könnte der Server sozusagen mit "Vollgas" 
senden, und der Client fischt sich immer das letzte Paket aus dem 
Puffer?

Gruß
Thomas

von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> Jetzt frage ich mich: wenn der Client nur alle 20 ms abruft, sind dann
> zwei Datensätze im Puffer?

Zunächst ja.

> Oder bekommt der Server erst eine Bestätigung dass die Daten angekommen
> sind, wenn der Client die Daten ausliest?

Auch. Irgenwann sind halt alle beteiligten Puffer voll.

> Und wie sieht das bei UDP aus: Könnte der Server sozusagen mit "Vollgas"
> senden, und der Client fischt sich immer das letzte Paket aus dem
> Puffer?

Auch da gibt es Puffer.

Zunächst muss dir klar werden, dass TCP in solchen isochronen 
Übertragungen nicht erste Wahl ist. TCP überträgt gnadenlos in der 
richtigen Reihenfolge. Auch wenn der Inhalt veraltet ist und niemanden 
mehr interessiert. Weshalb TCP beispielsweise bei Sprachübertragung 
(VoIP) nicht sinnvoll ist.

Wenn wie hier immer nur der letzte Stand interessiert, dann ist die 
Basis UDP (oder eines der exotischeren anderen Protokolle). Ein 
sinnvoller Ablauf kann sein, dass der Sender alle 10ms seinen Frame 
sendet und beim Empfänger ein Thread nur dafür zuständig ist, den 
letzten Frame in einen von zwei alternierenden Puffern im RAM zu 
schreiben. Dann ist im RAM immer der letzte Frame vorrätig - 
Übertragungsfehler inklusive. Wenn das eigentliche Programm auf 
Empfängerseite nicht mitkommt, dann tut das nichts zu Sache, dann wird 
halt mal ein empfangener Frame ignoriert.

von Kaj (Gast)


Lesenswert?

UDP bedeutet schlicht das keine Garantie übernommen wird, das einmal 
gesendete Daten auch ankommen. Wenn was gesendet wird, aber nicht 
ankommt, dann ist das so. Wird z.B. bei Streaming verwendet.

Bei TCP läuft das so, dass ein Paket, das nicht beim Empfänger ankommt, 
vom Empfänger neu angefragt wird.

Was du wie, wann, wo mit den Daten machst, ist ja deine Sache. Ob du da 
nun das letze oder erste oder 12503 Paket aus irgend einem Puffer holst, 
is ja dein Ding.

Grüße

von (prx) A. K. (prx)


Lesenswert?

PS: Mit "Frame" dürfte in diesem Kontext ein komplettes Bild gemeint 
sein, oder? Ist etwas missverständlich, weil Ethernet-Pakete ebenfalls 
als Frames bezeichnet werden.

von Thomas (Gast)


Lesenswert?

Ja, mit Frame ist in diesem Fall ein Bild gemeint.

Ich hatte über UDP mit Prüfsumme und einer Sequenznummer die in jedem 
Telegramm erhöht wird auch schon nachgedacht.
Es wird dann im Client nur das Datenpaket mit der höchsten Nummer 
ausgewertet. Ältere Pakete oder welche mit einem Prüfsummenfehler werden 
schlicht verworfen.

Ich schreib nochmal genauer was ich vorhabe:
Das ist kein Spiel im eigentlichen sinne, sondern es wird das Unreal 
Development Kit (UDK) eine zur Simulation einer Maschine benutzt. Die 
Steuerung dieser Maschine übernimmt eine SPS.
Ich habe das Prinzip schon laufen, nur ist es momentan so, dass aus dem 
UDK über eine dll lokal auf dem Rechner mit der SPS kommuniziert wird.
Das will ich jetzt auf Netzwerk ändern, weil fürs UDK ein PC mit guter 
Grafikkarte benötigt wird, und damit man das System relativ einfach an 
diverse andere Steuerungen oder auch Microcontroller anbinden kann.

Darum sollte gewährleistet sein, dass auf jeden Fall zu jedem Bild-Frame 
die Daten aus der Steuerung aktuell vorliegen.

Wie groß ist denn der interne Datenpuffer? Ich würde mal schätzen dass 
ein Datenpaket im Höchstfall (1000 Variablen) bis zu 50 kByte groß 
werden kann.

von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> Wie groß ist denn der interne Datenpuffer?

Wenn du das wissen musst, dann hast du schon verloren. Das ist weder 
klar definiert, noch ist es auf dem gleichen System stets gleich.

von Thomas (Gast)


Lesenswert?

A. K. schrieb:
> Wenn du das wissen musst, dann hast du schon verloren. Das ist weder
> klar definiert, noch ist es auf dem gleichen System stets gleich.

"Muss" nicht. Aber für eine Abschätzung ob es bei einem Client-Zyklus 
mit 20 ms sinnvoll ist, alle 1 ms Daten zu schicken.

Ich habe damit so gut wie keine Erfahrung. Ich stelle mir nur vor, der 
Puffer ist voll und dann ist das letzte Paket nur noch halb vorhanden.
Na gut, dann wird eben das Paket davor verwendet. Wichtig ist nur dass 
so ein Paket auf jeden Fall komplett in den Puffer passt.

von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> "Muss" nicht. Aber für eine Abschätzung ob es bei einem Client-Zyklus
> mit 20 ms sinnvoll ist, alle 1 ms Daten zu schicken.

Wie ich schon schrieb: Wenn du Puffer brauchst, dann mach dir welche. 
Selber. Schreib einen Thread, der nix anderes tut als Daten zu empfangen 
und ins RAM zu legen. In wieviele Kilo-, Mega- oder Gigabytes auch 
immer.

> Ich habe damit so gut wie keine Erfahrung. Ich stelle mir nur vor, der
> Puffer ist voll und dann ist das letzte Paket nur noch halb vorhanden.

Deshalb hatte ich vorhin alternierende Bildspeicher vorgeschlagen. Einer 
ist voll, der andere wird grad eben oder demnächst gefüllt und ist daher 
in undefiniertem Zustand. Halbe Ethernet-Frames gibts aber nicht. Die 
gibts nur ganz oder garnicht.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> "Muss" nicht. Aber für eine Abschätzung ob es bei einem Client-Zyklus
> mit 20 ms sinnvoll ist, alle 1 ms Daten zu schicken.

Was definitiv nicht sinnvoll ist: Mehr Daten zu schicken als der 
Empfänger aus dem Network-Stack abholt, in der Hoffnung, dass dabei 
zufällig genau jene Daten ankommen, die du haben willst.

Also: Bau das so, dass dein Empfängerprogramm alle Daten kriegt, die der 
Sender schickt. Wenn du dann welche verwerfen willst, dann tu es selbst. 
Nur dann hast du Kontrolle darüber, welche das sind.

von Thomas (Gast)


Lesenswert?

A. K. schrieb:
> Deshalb hatte ich vorhin alternierende Bildspeicher vorgeschlagen. Einer
> ist voll, der andere wird grad eben oder demnächst gefüllt und ist daher
> in undefiniertem Zustand.

Das ist schonmal eine gute Idee. Wenn aus irgendeinem Grund das Netzwerk 
mal kurzzeitig haken sollte, dann hat das auch keine Auswirkungen auf 
das Spiel.

Generell scheint UDP für diesen Anwendungsfall also geeigneter zu sein. 
Nur werde ich dann quasi als Befehlskanal noch eine zweite Verbindung 
über TCP aufbauen müssen, denn diese Daten sollten schon auf jeden Fall 
ankommen.
Und Daten vom Client an den Server sollten auch definitiv ankommen, 
falls z.B. ein Gegenstand vor einer Lichtschranke nur für ein Bild-Frame 
steht.

von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> Nur werde ich dann quasi als Befehlskanal noch eine zweite Verbindung
> über TCP aufbauen müssen, denn diese Daten sollten schon auf jeden Fall
> ankommen.

Und - O Wunder! - genau so arbeiten VoIP und Videotelefonie. SIP oder 
H323 per TCP für die Steuerung und RTP per UDP für Sprach/Video-Stream.

von Rolf Magnus (Gast)


Lesenswert?

Thomas schrieb:
> Generell scheint UDP für diesen Anwendungsfall also geeigneter zu sein.
> Nur werde ich dann quasi als Befehlskanal noch eine zweite Verbindung
> über TCP aufbauen müssen, denn diese Daten sollten schon auf jeden Fall
> ankommen.
> Und Daten vom Client an den Server sollten auch definitiv ankommen,
> falls z.B. ein Gegenstand vor einer Lichtschranke nur für ein Bild-Frame
> steht.

Du mußt dir halt im Klaren darüber sein, daß bei Paketverlust dieses 
Paket natürlich dann verzögert ankommt, nachdem es eben nochmal 
angefordert und erneut gesendet wurde, und daß sämtliche Pakete, die 
danach gesendet werden, so lange verzögert werden, bis das fehlende 
Paket nachgeliefert wurde. Die sind dann evt. zwar schon am 
Emfängerrechner angekommen, werden aber von dessen IP-Stack 
zurückgehalten.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> daß bei Paketverlust

TCP ist Streamorientiert, UPD Paketorientiert, daher kriegt man auf 
Anwendungsschicht eh nix von Paketen mit, da muss man sich selber drum 
bemühen Pakete zu erkennen, das sollte man auch im Hinterkopf behalten.

von Jürgen (jliegner)


Lesenswert?

Wenn man nur UDP braucht ist der GPLV2 Stack, den es mit/bei FreeRTOS 
gibt, sicher auch mal einen Blick wert. Hat jemand damit schon 
Erfahrungen?

http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/FreeRTOS_Plus_UDP.shtml

von Εrnst B. (ernst)


Lesenswert?

Jürgen Liegner schrieb:
> Wenn man nur UDP braucht ist der GPLV2 Stack, den es mit/bei FreeRTOS
> gibt, sicher auch mal einen Blick wert.

Gehts hier nicht um "PC-Programmierung", Spiele(-Server) usw?

Ich denk mal, jedes dafür in Frage kommende Betriebsystem wird schon 
einen UDP-Stack integriert haben.

von Jürgen (jliegner)


Lesenswert?

Sorry, habe ich übersehen.

von Thomas (Gast)


Lesenswert?

Ich hab mal nachgesehen wie das beim in der Industrie eingesetzten 
Profinet IO gemacht wird. Das setzt zwar direkt auf der MAC Ebene auf, 
aber ist demnach wie auch UDP paketorientiert.

Dort gibt es ein festes Aktualisierungsraster z.B. einer 
Ausgabebaugruppe von 1 ms. Der Teilnehmer akzeptiert bis zu drei 
Aktualisierungszyklen ohne Daten erhalten zu haben, danach geht er in 
Fehlerzustand und setzt seine Ausgänge in einen sicheren Zustand.
Daraus folgt, dass bei Profinet einzelne Datenpakete unter Umständen 
einfach unter den Tisch fallen. Obwohl ich das schon eingesetzt habe war 
mir das bisher gar nicht klar. So würde meine UDP-Lösung dann (bis auf 
den Fehlerzustand) auch funktionieren.

Bei Profibus (auch wenn das mit Profinet nicht unbedingt vergleichbar 
ist, Token-Passing vs. CSMA) war das anders. Dort gab es ein Retry Limit 
was im Normalfall in einem Netz ohne Repeater oder Ringstrukturen auf 1 
steht. D.h. ein Telegramm wird auf jeden Fall zugestellt. Wenn nicht, 
dann geht der Teilnehmer auf Fehler.

von (prx) A. K. (prx)


Lesenswert?

Es läuft letztlich auf die Frage hinaus, ob man im Steuerkanal mit den 
Nebeneffekten von TCP leben kann, oder auf Basis von IP oder UDP einen 
eigenes der Anwendung angepasstes Protokoll zur Sicherstellung der 
Übertragung kritischer Informationen drauf setzt.

Man vergisst angesichts der Dominanz von TCP und UDP leicht, dass es 
daneben noch einen ziemlichen Rattenschwanz anderer Transport Layer 
Protokolle gibt. Man ist mit solchen Problemen selten der Erste. Nur 
kann man nicht unbedingt drauf wetten, dass die im TCP/IP Stack schon 
implementiert sind.

von Trundle T. (shaheed)


Lesenswert?

Anmerkung zur Paketgröße von Udp als auch Tcp-Paketen: ohne besondere 
Optionen sind nur max. 1.5kByte Pakete zu empfangen und zu senden.
Zusätzlich ist der bereits erwähnte Umstand zu beachten dein 
Betriebssystem (bzw sein Stack) packt seine Ethernetdaten direkt 
hintereinander in seinen Puffer so das es nicht ohne weitere 
Codierung/Makierung der Daten möglich ist diese einzelnen Paketen 
zuzuweisen!

von (prx) A. K. (prx)


Lesenswert?

Trundle Trollkönig schrieb:
> Anmerkung zur Paketgröße von Udp als auch Tcp-Paketen: ohne besondere
> Optionen sind nur max. 1.5kByte Pakete zu empfangen und zu senden.

Das ist Sache des Network Layers (Ethernet). In TCP hat man es mit einem 
Stream zu tun, daher ist die Paketgrösse wenig relevant.

In IP sind Pakete möglich, die grösser als ein Ethernet Frame sind, 
somit gilt das auch für UDP. Weil sie ggf. fragmentiert werden.

> Betriebssystem (bzw sein Stack) packt seine Ethernetdaten direkt
> hintereinander in seinen Puffer so das es nicht ohne weitere
> Codierung/Makierung der Daten möglich ist diese einzelnen Paketen
> zuzuweisen!

Das gilt für TCP. UDP Pakete bleiben erhalten.

: Bearbeitet durch User
von Trundle T. (shaheed)


Lesenswert?

ich hatte das vom TO so verstanden, das er immer ein Paket, verpackt in 
nur einem Ethernetpaket (1 Frame = 1 Ethernetpaket zumindest kenn ich 
das so), mit gleicher Payloaddatenstruktur, alle was weiß ich wieviel ms 
versenden möchte und davon die aktuellsten Daten dann weiterverarbeiten 
möchte. Dazu wäre es nötig die nicht mehr erkenntlich Paketstruktur im 
tcp-stack, falls er Tcp-Protokoll verwendet, durch selbst implementierte 
Markierungen des Payloads wieder herzustellen. Und wenn es nur 1 
Ethernetpaket sein soll ist er nunmal an die maximale Ethernetpaketgröße 
gebunden. Aber ich glaube mit vlan-tag kann man auch mehr als 1.5k 
verschicken.

: Bearbeitet durch User
von mar IO (Gast)


Lesenswert?

Habe ich das richtig verstanden?

1.2 ...
1.3 Der Client sendet die Zustände der Ausgänge mit einem Zeitstempel an 
den PC.

2.1 Der Server, PC, berechnet anhand der empfangenen Zustände der 
Ausgänge die neuen Zustände der Eingänge und schickt das Ergebnis an den 
Client zurück.
2.2 Nebenbei wird mittels dem UDK ein Spiel (Anlage) ausgeführt, das auf 
dem PC-Monitor dargestellt wird.

1.1 Der Client empfängt die neuen Zustände der Eingänge.
1.2 Der Client bzw. die SPS arbeitet den nächsten Zyklus ab.
1.3 Der Client sendet die Zustände der Ausgänge mit einem Zeitstempel an 
den PC.

2.1 ...

von (prx) A. K. (prx)


Lesenswert?

Trundle Trollkönig schrieb:
> Ethernetpaket (1 Frame = 1 Ethernetpaket zumindest kenn ich das so),

Das wurde bereits oben geklärt, sein "Frame" hat nichts mit Ethernet zu 
tun: 
Beitrag "Re: Fragen zur Datenübertragung mit TCP oder UDP"

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

Hi,
damit man sich mal was darunter vorstellen kann, gibts hier es ein Video 
was mit der bisherigen Version (Kommunikation lokal) umgesetzt wurde:
http://www.youtube.com/watch?v=KzuPgLJ88UU

Das "Spiel" (Simulation ist der passendere Ausdruck) bildet sozusagen 
die Realität ab. Die roten Linien stellen Lichtschranken dar, die SPS 
steuert in dem Fall einfach ein paar Motoren an.

@mar IO:
Beide Programme sind in keiner Weise synchronisiert.

Der Zyklus der Simulation sieht so aus:
1. Simulation liest die Befehle aus der SPS (z.B. Motor an oder aus)
2. Berechnung der Physik
3. Zurückschreiben vom Signalen an die SPS (z.B. Lichtschranke belegt)
4. Rendern des Bildes

Die SPS hat im Normalfall ebenfalls eine zyklischen oder freilaufenden 
Task. Liest die Eingänge ein (z.B. Lichtschranke belegt) und startet 
daraufhin einen Motor.


Bezüglich UDP schreibe ich mir erstmal ein kleines Testprogramm um zu 
sehen wie sich die Kommunikation da überhaupt verhält. Bezüglich 
Paketgröße findet man widersprüchliche Angaben im Netz. Wenn die Daten 
über eine DSL Leitung gehen wird ja auf jeden Fall auf MTU Größe 
fragmentiert. Aber im LAN dürfte das doch nicht der Fall sein.

von (prx) A. K. (prx)


Lesenswert?

Thomas schrieb:
> Bezüglich UDP schreibe ich mir erstmal ein kleines Testprogramm um zu
> sehen wie sich die Kommunikation da überhaupt verhält. Bezüglich
> Paketgröße findet man widersprüchliche Angaben im Netz. Wenn die Daten
> über eine DSL Leitung gehen wird ja auf jeden Fall auf MTU Größe
> fragmentiert. Aber im LAN dürfte das doch nicht der Fall sein.

Es gibt immer eine MTU. Im Ethernet ist die 1500, beim DSL leicht 
darunter. Das bedeutet aber nicht, dass UDP Pakete darauf limitiert sein 
müssen. Allerdings müssen IPv4-Stacks nicht mehr als 576 Bytes 
reassemblieren können, wobei dieser Wert aber allenfalls bei 
Zwergsystemen zu finden ist, nicht bei PCs.

: Bearbeitet durch User
von mar IO (Gast)


Lesenswert?

Thomas schrieb:
> Wenn die Daten
> über eine DSL Leitung gehen wird ja auf jeden Fall auf MTU Größe
> fragmentiert. Aber im LAN dürfte das doch nicht der Fall sein.

Bei Ethernet gibt es eine maximale Paketgröße. Mittels Jumbo-Frames kann 
man das im lokalen Netz noch steigern. Das ist nützliche wenn man große 
Menge an Daten über Netzwerk verschiebt, da man mehr Nutzdaten pro 
Sekunde übertragen kann.

Im allgemeinen Interessiert die MTU nicht, da der UDP-Stack selber seine 
Pakete entsprechend aufteilt.

von (prx) A. K. (prx)


Lesenswert?

mar IO schrieb:
> Mittels Jumbo-Frames kann
> man das im lokalen Netz noch steigern.

Im Prinzip ist das zwar richtig, es wird hier jedoch eher zur Verwirrung 
beitragen, als ihm wirklich helfen. So lange man noch mit normalem 
Ethernet und TCP/IP kämpft, sollte man von Jumbo Frames die Finger 
lassen. Danach besser auch.

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

Mit einem Python UDP Socket bekomme ich bis zu 65515 Bytes mit einem 
sendto() geschickt.
In der Wireshark-Anzeige sieht man dann gesplittete Einzelpakete zu je 
max. 1480 Bytes, angezeigt als "Fragmented IP protocol". Das Zerlegen 
und zusammensetzen scheint also auf IP Layer abzulaufen.

Sieht doch eigentlich zuverlässig aus, die Datenmenge reicht mir dicke 
aus.

von U.Hertlein (Gast)


Lesenswert?

Thomas schrieb:
> Sieht doch eigentlich zuverlässig aus, die Datenmenge reicht mir dicke
> aus.

'Zuverlässig' ist es eben bei UDP nicht.  Wenn ein Frame kaputt ist ist 
das ganze datagram weg.  Kann im LAN funktionieren, muss aber nicht.

Wenn du über DSL/WAN übertragen willst musst du unterhalb der MTU 
bleiben.

/uli

von (prx) A. K. (prx)


Lesenswert?

U.Hertlein schrieb:
> Wenn du über DSL/WAN übertragen willst musst du unterhalb der MTU
> bleiben.

Weshalb?

von mar IO (Gast)


Lesenswert?

A. K. schrieb:
> U.Hertlein schrieb:
>> Wenn du über DSL/WAN übertragen willst musst du unterhalb der MTU
>> bleiben.
>
> Weshalb?

Das würde mich auch interessieren, denn im allgemeinen interessiert die 
MTU nicht und vor allem in diesem Fall!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.