Datenübertragung per TCP und UDP

#5228258
Lesenswert?

Hallo zusammen,

kurz die Ausgangsposition:
Ich soll Daten von einem Evaluationsboard (mit Freescale 
Microcontroller) an meinen Laptop per Ethernet senden und würde mich 
über eine fachliche Meinung von euch freuen. Ich bekomme live einen 
Datenstrom auf mein Board und diese Daten will ich dann sofort 
weiterleiten.
Aktuell sende ich die Daten per TCP von meinem Board zum Laptop: das 
Board ist der Server und auf meinem Rechner läuft ein Python Client der 
die Daten empfängt und verarbeitet.
Die Datenübertragung funktioniert auch ganz gut jedoch muss mein Server 
auf ein ACK vom Client warten (über Wire shark sehe ich, dass ich 200 ms 
auf das ACK warten muss).
Die erste Frage ist somit, ob es bei dieser Verbindung immer nötig ist, 
dass ich auf das ACK vom Client warten muss bevor der Server ein neues 
Paket sendet? In der Wartezeit "fülle" ich dann wieder meinen 
Ethernetsendepuffer mit den Livedaten.

Die zweite Frage ist, ob eine Verbindung per UDP dieses Problem lösen 
würde oder ob ich dann zu viele Fehler habe wenn Daten nicht?

Vielen Dank für eure Hilfe.

Matthias
Moderator Persönliche Seite #5228287
Lesenswert?

Matthias X. schrieb:
> Die erste Frage ist somit, ob es bei dieser Verbindung immer nötig ist,
> dass ich auf das ACK vom Client warten muss bevor der Server ein neues
> Paket sendet?

Das kommt auf den Client an, ob er das so akzeptiert. Allerdings ist 
diese ACK-Geschichte bei TCP ziemlich witzlos, da die TCP-Schicht 
bereits sicherstellt, dass die Daten auch ausgeliefert werden. Kommen 
sie aus irgendeinem Grunde beim Client nicht an, bekommt der Server 
einen Fehler präsentiert.

> In der Wartezeit "fülle" ich dann wieder meinen
> Ethernetsendepuffer mit den Livedaten.

Nicht verkehrt.

>  Die zweite Frage ist, ob eine Verbindung per UDP dieses Problem lösen
> würde oder ob ich dann zu viele Fehler habe wenn Daten nicht?

"Verbindung per UDP" ist ein Widerspruch in sich:

TCP - verbindungsorientierte Kommunikation
UDP - verbindungslose Kommunikation

Oder meinst Du, Du stehst in dem Moment mit dem Empfänger "in 
Verbindung", wenn Du einen Brief in einen Briefkasten wirfst?
Gast #5228293
Lesenswert?

Matthias X. schrieb:
> über Wire shark sehe ich, dass ich 200 ms
> auf das ACK warten muss

Dafür hat der Herr Nagle gesorgt:
https://de.wikipedia.org/wiki/Nagle-Algorithmus

bei UDP gibt es das nicht, dafür können Pakete verloren gehen. Bei einer 
Punkt zu Punkt Verbindung allerdings eher selten, nur wenn der Gegner 
keine Buffer mehr hat. Dafür müsste man dann selber eine Sicherung 
darüber bauen.
#5228294
Lesenswert?

Matthias X. schrieb:
> Die erste Frage ist somit, ob es bei dieser Verbindung immer nötig ist,
> dass ich auf das ACK vom Client warten muss bevor der Server ein neues
> Paket sendet?

Da gilt Radio Eriwan: Es kommt darauf an. TCP kennt einen 
Fenstermechanismus, bei dem der Sender munter plappert und ab und an 
kommt ein Sammel-ACK. Der Nachteil dabei: Der Sender muss alle Frames 
weiter auf Abruf halten, bis er die Empfangsbestätigung bekommt. Hat 
dein Eval-Board so viel Speicher?


> Die zweite Frage ist, ob eine Verbindung per UDP dieses Problem lösen
> würde oder ob ich dann zu viele Fehler habe wenn Daten nicht?

Auch hier die gleiche Antwort: Es kommt darauf an. UDP hat immer 
Datenverluste. Wie hoch die Verluste sind, hängt von x Parametern ab. 
Wenn dein Auswerteprogramm damit leben kann: Prima, UDP ist einfacher, 
hat weniger Overhead.
#5228302
Lesenswert?

Matthias X. schrieb:
> Die erste Frage ist somit, ob es bei dieser Verbindung immer nötig ist,
> dass ich auf das ACK vom Client warten muss bevor der Server ein neues
> Paket sendet?

Nö, muss man bei TCP nicht - aber je nach verwendetem IP Stack müsste 
man eventuell viel umprogrammieren.

Besser ist dann der fiese Trick das völlig fertige TCP Paket einfach 2x 
zu senden - der Client antwortet in diesem Falle sofort mit ACK.

ACK Delay auszuschalten ist im Zeitalter des Internets und Gigabit eine 
richtig blöde Idee.  UDP über WLAN (Laptop!) wird lustig (Stichworte 
Retransmit und Packet loss).
Gast #5228305
Lesenswert?

> ACK Delay auszuschalten ist im Zeitalter des Internets und Gigabit
> eine richtig blöde Idee.

Frühe konnte man das über einen Registry Eintrag machen. Jetzt nicht 
mehr (finde ich auch richtig so). Immerhin können Anwendungsprogramme 
diese Option noch für jede Verbindung einzeln einstellen.

Nur leider geht das in den mir bekannten Web Browsern nicht. Man müsste 
dort wohl den Quelltext ändern.
Gast #5228323
Lesenswert?

Stefan U. schrieb:
> Linux hat den Algorithmus auch, aber Linux erkennt dazu inkompatible
> Verbindungspartner

Wenn der Gegner fix ist und man sich darauf verlassen möchte mag das ok 
sein, aber der Standard ist das delayed ACK. Man kann es mit TCP_NODELAY 
versuchen abzuschalten, aber soweit ich weiss ist es ist kein muss für 
den Gegner, wenn er nicht will oder kann darf er das ignorieren.

Mittlerweile gibt es noch ein TCP_QUICKACK und das OS kann 
Protokollabhängig das ACK schnellstmöglich schicken.
#5228329
Lesenswert?

Das Problem entsteht, wenn man einfache TCP Stacks wie µIP einsetzt, die 
nur einen einzigen Ethernet-Frame puffern. Dann muss man den bestätigt 
bekommen bevor man den nächsten aufbauen kann. Und das dauert, da die 
üblichen Stacks erst sehr verspätet bestätigen.

Abhilfe: Jeden Frame zweimal direkt hintereinander senden. Dann glaubt 
der Stack des Partners, dass etwas schief lief, und bestätigt den 
zweiten sofort. Das braucht zwar doppelte Rate, aber die kriegt man dann 
auch.
#5228344
Lesenswert?

Matthias X. schrieb:
> Die zweite Frage ist, ob eine Verbindung per UDP dieses Problem lösen
> würde

Im Prinzip ja. Aber nur im lokalen Netz.

> oder ob ich dann zu viele Fehler habe wenn Daten nicht?

Selten. Gelegentliche Fehler muss man trotzdem einrechnen. Ob man damit 
leben kann hängt von der Aufgabe ab. Benötigt man zwingend alle Daten, 
dann muss man auf UDP eine Übertragungswiederholung einbauen. Geht es 
aber beispielsweise um die Übertragung von Daten, bei denen die 
Aktualität wichtiger ist als die Vollständigkeit (z.B. Messwerte, 
Audio/Video), dann ignoriert man fehlende Daten einfach.

Über Internet ist UDP unabhängig davon für Übertragung grösserer Mengen 
allenfalls verwendbar, wenn man die Datenrate auf die wahrscheinlich 
übertragbare Rate drosselt. TCP macht das selbst, UDP nicht.
#5228361
Lesenswert?

Erstmal vielen Dank an alle!

A. K. schrieb:
> Das Problem entsteht, wenn man einfache TCP Stacks wie µIP einsetzt, die
> nur einen einzigen Ethernet-Frame puffern. Dann muss man den bestätigt
> bekommen bevor man den nächsten aufbauen kann. Und das dauert, da die
> üblichen Stacks erst sehr verspätet bestätigen.
>
> Abhilfe: Jeden Frame zweimal direkt hintereinander senden. Dann glaubt
> der Stack des Partners, dass etwas schief lief, und bestätigt den
> zweiten sofort. Das braucht zwar doppelte Rate, aber die kriegt man dann
> auch.


Ja ich verwende genau diesen Stack deshalb wohl das Problem. Danke für 
den Tipp ich werde das gleich mal ausprobieren.

Frank M. schrieb:
> Oder meinst Du, Du stehst in dem Moment mit dem Empfänger "in
> Verbindung", wenn Du einen Brief in einen Briefkasten wirfst?

War etwas umgangssprachlich formuliert aber du hast das schon richtig 
verstanden: "UDP Verbindung" im Sinne von ich sende Daten per UDP und 
mein Client empfängt diese Daten.
Gast #5228408
Lesenswert?

Matthias X. schrieb:
> Ja ich verwende genau diesen Stack deshalb wohl das Problem.

Das Problem tritt aber da auch nur dann auf wenn man z.B. einen HTTP 
Server hat und der PC Browser als Client nicht beeinflusst werden kann 
wie er seinen Socket aufmacht.
Du schriebst aber Eingangs das du einen eigenen Python Client hast, da 
müsste man die Socket Option TCP_NODELAY setzen können und das Problem 
damit etwas sauberer lösen. Bin in Python nicht fit, aber die Python 
socket lib hat sowas hier:
1
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
Gast #5228462
Lesenswert?

Matthias X. schrieb:
> War etwas umgangssprachlich formuliert aber du hast das schon richtig
> verstanden: "UDP Verbindung" im Sinne von ich sende Daten per UDP und
> mein Client empfängt diese Daten.

Eine UDP "Verbindung" nennt man Session. Ähnlich wie eine TCP-Verbindung 
ist sie durch Source IP Adresse, Source UDP-Port, Destination IP Adresse 
und Destionation UDP-Port definiert. Zusätzlich manchmal durch die 
schwammige Bedingung, dass die UDP-Pakete einer Session einem 
"gemeinsamen Zweck" dienen.

Typischerweise verwendet eine UDP-Session beidseitig "connected" 
Sockets, also Socket, bei denen connect() aufgerufen wurde. Man kann 
UDP-Sessions auch ohne connect(), also mit "unconnected" Sockets 
aufbauen. Da connect() es bequemer macht (man gibt damit die Destination 
IP Adresse und den Destionation UDP-Port vor) ist connect() typisch.
Gast #5228541
Lesenswert?

Bei "zeitkritischen Sachen" auf uC's mit z.B. uIP als Stack würde ich 
immer UDP nehmen, da das Timeout beim TCP-ACK laut Standard bis zu 500ms 
betragen kann. Allerdings würde ich dann selbst die Daten mit einer 
Checksumme und einem Lebenszähler absichern. Das geht dann trotzdem 
immer noch wesentlich schneller als TCP mit seinem langen ACK.

Aber wie das oben erwähnt wurde, bringt in der Regel nur in einem 
lokalen Netzwerk was. Denke aber mal, daß das genau hier gemeint ist. 
Mit zeitkritisch meine ich lediglich Sachen die flotter gehen müssen, 
damit war keine Echtzeit gemeint. Im Grundsatz sind TCP/IP o. UDP/IP 
nicht echtzeitfähig.
#5228934
Lesenswert?

In der engl. Wiki ist das Problem (siehe auch Johannes Beiträge) gut 
beschrieben:

[The Nagle] algorithm interacts badly with TCP delayed acknowledgments, 
a feature introduced into TCP at roughly the same time in the early 
1980s, but by a different group. With both algorithms enabled, 
applications that do two successive writes to a TCP connection, followed 
by a read that will not be fulfilled until after the data from the 
second write has reached the destination, experience a constant delay of 
up to 500 milliseconds, the "ACK delay". For this reason, TCP 
implementations usually provide applications with an interface to 
disable the Nagle algorithm. This is typically called the TCP_NODELAY 
option.

https://en.wikipedia.org/wiki/Nagle%27s_algorithm

Da du bereits mit Wireshark sniffst, siehst du ja, ob genau dies 
zutrifft.
#5228965
Lesenswert?

A. K. schrieb:
> Das Problem entsteht, wenn man einfache TCP Stacks wie µIP einsetzt, die
> nur einen einzigen Ethernet-Frame puffern. Dann muss man den bestätigt
> bekommen bevor man den nächsten aufbauen kann. Und das dauert, da die
> üblichen Stacks erst sehr verspätet bestätigen.

Dann sollte aber auch nur ein entsprechend kleines Window vereinbart 
werden, wie Daten gepuffert werden können. Wird das Ack denn tatsächlich 
auch delayed, wenn das Window bereits voll ist?

Oder meinst du das wörtlich, dass der zuletzt gesendete Ethernet Frame 
gepuffert wird (auch wenn bspw. nur ein Byte übertragen wurde) und für 
diesen Frame wird dann auf ein Ack gewartet?! Das wäre in der Tat ein 
Problem (und ich würde dann auch nicht mehr von einer TCP 
Implementierung sprechen, auch falls das rein protokolltechnisch noch ok 
sein könnte).
Gast #5228988
Lesenswert?

Mikro 7. schrieb:
> Oder meinst du das wörtlich, dass der zuletzt gesendete Ethernet Frame
> gepuffert wird (auch wenn bspw. nur ein Byte übertragen wurde) und für
> diesen Frame wird dann auf ein Ack gewartet?!

Wie sonst sollte sichergestellt werden, daß der Frame auch richtig 
angekommen ist? Im Fehlerfall muß er ja noch mal gesendet werden, der 
Stack muß ihn also noch vorrätig haben.

MfG Klaus
#5228999
Lesenswert?

Nicht ganz so wörtlich, denn dieser eine Puffer wird ja für den Empfang 
des Ack-Frames gebraucht. Weshalb die Anwendung einen ggf. zu 
wiederholenden Frame reproduzieren muss.

Dunkels Werk ist absolute Minimalistik. Da ist natürlich auch kein 
Socket-API dahinter. Mehr als ein Frame ist nicht vorgesehen. Die 
Anwendung schickt den Frame raus und wenn nach Timeout keine passende 
Bestätigung kommt, dann baut sie ihn nochmal und schickt ihn erneut. 
Mehr ist da nicht.

"In order to reduce memory usage, the TCP in uIP does not implement a 
sliding window for sending and receiving data. Incoming TCP segments are 
not buffered by uIP, but must be processed immediately by the 
application. Note that this does not prevent the application from 
buffering the data by itself. For outbound data, uIP cannot have more 
than one outstanding TCP segment per connection."

http://www.dunkels.com/adam/download/uip-doc-0.5.pdf
#5229006
Lesenswert?

Dunkels war sich der Problematik bewusst und hatte einen optionalen Hack 
gebaut, der den Frame künstlich fragmentiert. Sollte das Ack Problem 
lösen. Hat bei mir aber nicht funktioniert.

Dem Trick mit den der direkten Wiederholung der Frames bin ich erst 
später bei einem Wiznet Chip begegnet. Diese Dinger haben TCP/IP intern. 
Da begegnete ich unter bestimmten Randbedingungen im LAN-Trace solchen 
Dopplern.
#5229024
Lesenswert?

Mikro 7. schrieb:
> Ui, das ist in der Tat minimalistisch und da lauern böse Fallstricke.

Yep. Eine universelle Lösung streng nach RFCs ist das nicht.

Ich hatte damit mit dem ATmega32 einen Datenlogger gebaut, der 
einerseits ein paar simple Webseiten als Statusanzeige liefert, 
andererseits 0,5MB Logdaten. Mit TCP dauerten diese 0,5MB viele Minuten. 
Weshalb ich für Übertragung innerhalb vom LAN zusätzlich auch simples 
UDP verwende: Die Daten Frame für Frame mit einer Sequenznummer versehen 
und rausfeuern. Oft kommt es komplett an, wenn nicht, dann fordert die 
PC-Anwendung das eben nochmal an. Über Internet geht natürlich nur TCP.
#5229040
Lesenswert?

Er (Dunkels) hat seine Implementierung zumindest gut dokumentiert. Die 
Idee, die Buffer in die Applikation zu verlagern, ist nicht schlecht. In 
letzter Konsequenz sollte die Applikation dann auch die Window Size 
vorgegeben. Der Schritt zu einem "konformen" TCP/Stack sollte nicht mehr 
weit sein. Das Interface zur App ist natürlich entsprechend "speziell" 
(durch die notwendigen callbacks).

A. K. schrieb:
> Über Internet geht natürlich nur TCP.

Wieso? Gerade wenn man keinen TCP/IP Stack hat, bietet sich doch UDP mit 
einfachen Send/Ack Handshake an!?
#5229063
Lesenswert?

Mikro 7. schrieb:
> Wieso? Gerade wenn man keinen TCP/IP Stack hat, bietet sich doch UDP mit
> einfachen Send/Ack Handshake an!?

Ich beschrieb hier was ich implementiert hatte. Nicht was ich hätte 
implementieren können. Ein AVR ist zwar kein Rennpferd, aber wenn der 
wie bei mir ungebremst eine Folge von UDP Frames ohne Quittung 
rausbläst, dann ist er schneller als mancher DSL Uplink.
#5229144
Lesenswert?

Barrex schrieb:
> Bei "zeitkritischen Sachen" auf uC's mit z.B. uIP als Stack würde ich
> immer UDP nehmen, da das Timeout beim TCP-ACK laut Standard bis zu 500ms
> betragen kann.

Das ganze soll später sowieso auf einem Linux-System laufen. Ich hoffe, 
dass ich dann nicht 200 ms auf ein ACK warten muss. Dann wäre mein 
Problem sowieso gelöst - ich muss zum Glück nicht echtzeitfähig sein.
Gast #5229176
Lesenswert?

> Dann sollte aber auch nur ein entsprechend kleines Window
> vereinbart werden

µIP sende diese Information ja auch korrekt nach Windows. Und µIP sendet 
das ACK auch immer schnell. Nur Windows geht trotzdem einfach davon aus, 
das die Gegenstelle eine größere Windows size hat.

> Dunkels war sich der Problematik bewusst und hatte einen optionalen Hack
> gebaut, der den Frame künstlich fragmentiert. Sollte das Ack Problem
> lösen. Hat bei mir aber nicht funktioniert.

Bei mir auch nicht. Und die Variante, das Frame 2x zu senden hat bei mir 
auch nicht funktioniert.
#5229304
Lesenswert?

Matthias X. schrieb:
> UDP ist bei meiner Version vom uIP Stack noch nicht implementiert
> deswegen war der erste Ansatz über TCP/IP.

UDP ohne TCP/IP Stack: Wenn man sowieso nur ein Send/Ack Protocol (ohne 
Window) fährt (also kein Packet Reorder) und die kleinste Packet Size 
ausreicht (ohne Gefahr von IP Fragmentation), dann muss man "lediglich" 
die UDP/IP Header kodieren/dekodieren + ggf. Prüfsumme.

(Edit: +Re-Send after Timeout/NAK +Duplicate-Bit)

> Die Vor- und Nachteile von
> TCP sind mir bekannt, weswegen für meinen Anwendungsfall TCP auch die
> bessere Lösung ist.

uIP bietet kein "echtes" TCP an. Weder aus Protokollsicht noch aus 
Applikationssicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren