Ich erwäge, von TCP auf UDP umzusteigen, bin aber unsicher, ob meine Gedanken dazu korrekt sind. Im Folgenden meine ich mit "Anwendung" meine Programme sowohl auf dem PC als auch auf dem µC. Betriebsystem und IP Stack zähle ich nicht dazu. Ich habe ein paar Basteleien hinter mir, wo selbst gebaute Elektronik über Ethernet oder WLAN vom PC aus ferngesteuert wurde. Da ich zuvor sehr viel Erfahrung mit seriellen Ports und Modems gesammelt hatte, kam es mir "natürlich" vor, das TCP Protokoll zu verwenden. Allerdings ist mir bewusst geworden, dass TCP womöglich nicht die beste Wahl war. Auf folgende Schwachpunkte bin ich gestoßen: 1) Der Verbindungsaufbau kostet (unnötige?) zusätzliche Zeit. 2) TCP scheint sicher zu stellen, dass Daten vollständig, korrekt und in der richtigen Reihenfolge beim Empfänger ankommen. Aber im Störungsfall kann die Übertragung für eine ungewisse Zeitspanne ins Stocken geraten oder gar ganz abbrechen. Dass heisst, dass meine Anwendung auf Abbrüche und Timneouts reagieren muss. Timeouts insbesondere dann, wenn meine Anwendung kürzere Aussetzer (z.B. 10 Sekunden) schon als Fehler werten soll, die beim IP Stack noch nicht zum Abbruch führen würden. 3) Wenn mein µC von vielen PC's zugleich angesprochen werden soll, muss er entweder mehrere TCP Verbindungen zugleich verwalten (was Speicher kostet) oder die Verbindungen müssen immer möglichst schnell wieder getrennt werden und für andere Kommunikationspartner Platz zu machen. Das wiederum würde den Netzwerk Traffix unnötig erhöhen und kommt mir als "unsauber" wenn nicht gar unerwünscht vor. 4) Ich kann mich nicht drauf verlassen, dass ein zusammenhängender String auch am Stück ankommt. Zum Beispiel ein Befehl wie "LIGHTS OFF" könnte beim Empfänger zerstückelt in zwei Paketen ankommen, vor allem wenn ich aus einer Linux oder Windows Anwendung heraus sende. Der Empfänger braucht also Pufferspeicher, um die Empfangenen zeichen zu sammeln, bis das Ende eines Befehl (z.B. anhand eines \n) erkannt wurde. Da es bisher immer so war, gehe ich davon aus, dass meine Anwendungen immer nur kleine Pakete von weit unter 1KB senden und empfangen. Der PC sendet ein Paket als Befehl und erwartet ein Paket als Antwort. Oder der µC sendet ungefragt Ereignisse zum PC. Nun frage ich mich, ob ich künftig nicht besser auf UDP umsteige. Davon verspreche ich mir ein paar Vorteile, aber ich weiß nicht, ob meine Annahmen korrekt sind. 1) Verbindungsaufbau und Abbau entfallen. 2) Wenn ich ein Paket sende, kommt es irgendwann richtig und vollständig beim Empfänger an, sofern die Übertragungsstrecke nicht defekt oder massiv gestört ist. 3) Gesendete Pakete bis maximal 1KB werden nie zerstückelt. 4) Ich kann mit mehreren PC's annähernd gleichzeitig Kommandos zu einem einzigen UDP Port auf einem µC senden. 5) Der µC kann erkennen, von welcher IP+Port ein Kommando kam, so weiß er, wohin er die Antwort schicken muss. 6) Meine Anwendung muss also die empfangenen Daten nicht sammeln, denn sie kommen immer am Stück als Paket an. 1 Paket = 1 Kommando oder Antwort. 7) Der Einzige Fehler, auf den meine Anwendung reagieren muss, sind Timeouts. Und selbst das kann unter Umständen entfallen, nämlich dann, wenn die gesendeten Daten nicht wichtig waren oder ein Wiederholmechanismus außerhalb der Anwendung existiert. Dann wäre UDP ja viel einfacher zu verwenden, als TCP. Oder nicht? Ich habe noch nie UDP verwendet. C/C++ kann es ganz sicher, wie sieht es mit Java aus? Da kenne ich nur Streams.
tl;dr: Was hast Du eigentlich vor? ...aber Hauptsache IoT im Titel stehen :rolleyes:
Stefan U. schrieb: > Dann wäre UDP ja viel einfacher zu verwenden, als TCP. Oder nicht? Ja, stimmt fast alles. Wenn UDP sich aber dann doch nicht speziell für dein Thing eignet müßtest du wieder auf TCP gehen. (µC erkennt nicht auf welchem Port UDP ankommt, sonder muß dort lauschen)
Stefan U. schrieb: > Nun frage ich mich, ob ich künftig nicht besser auf UDP umsteige. Mach das. Die von Dir aufgeführten Schwachpunkte von TCP sind alle zutreffend. Es ist halt für sichere Verbindungen gedacht, d.h. Du weißt jederzeit, ob Dein Paket "drüben" ankam oder nicht. > Davon > verspreche ich mir ein paar Vorteile, aber ich weiß nicht, ob meine > Annahmen korrekt sind. > > 1) Verbindungsaufbau und Abbau entfallen. Korrekt. > 2) Wenn ich ein Paket sende, kommt es irgendwann richtig und vollständig > beim Empfänger an, sofern die Übertragungsstrecke nicht defekt oder > massiv gestört ist. Darauf würde ich mich nicht verlassen. Im Zweifel sollte Dein Gegenpart schon eine Antwort über UDP schicken, um mitzuteilen, dass Deine Nachricht angekommen ist. Ich persönlich arbeite da gern mit einer Statemachine. Ich sende eine Nachricht, warte aber nicht auf Antworten und lasse den µC was anderes machen. Kommt dann irgendwann eine Antwort, dann vermerke ich die dazugehörige Nachricht als erfolgreich versendet. Aber dieses Vorgehen ist Geschmackssache. Es kommt immer drauf an, wie wichtig es ist zu wissen, ob die Nachricht ankam oder nicht. > 3) Gesendete Pakete bis maximal 1KB werden nie zerstückelt. Falsch. Beachte die MTU: https://de.wikipedia.org/wiki/Maximum_Transmission_Unit Bei einem Wert von 576, wobei dann noch für IP-Header 20 Bytes, für UDP zusätzlich 8 Bytes draufgehen, können auch noch weitere "IP options" eingefügt werden. Daher würde ich nicht über 512 Bytes gehen. 576 ist der minimale Wert für die MTU, der möglich ist. Mit 512 Bytes bist Du daher immer auf der sicheren Seite. Ohne "IP options" wäre die theoretisch maximal mögliche Paketgröße, die nicht zerstückelt würde, 548. Aber das ist alles theoretisch. Wenn Du UDP-Messages nur in Deinem lokalen Netzwerk verschicken willst und nicht quer übers Internet, dann gehen selbstverständlich auch höhere Werte. Bei Ethernet ist zum Beispiel ein typischer Wert der MTU 1500. Ziehe dann noch Headergrößen für IP und UDP ab und Du weisst, wie weit Du gehen kannst. > 4) Ich kann mit mehreren PC's annähernd gleichzeitig Kommandos zu einem > einzigen UDP Port auf einem µC senden. Kommt auf den IP-Stack auf dem µC an, ob er "annähernd gleichzeitige" Nachrichten verarbeiten kann. > 5) Der µC kann erkennen, von welcher IP+Port ein Kommando kam, so weiß > er, wohin er die Antwort schicken muss. Ja, das ist aber eine Trivialität. Diese Info hast Du bei TCP genauso. > 6) Meine Anwendung muss also die empfangenen Daten nicht sammeln, denn > sie kommen immer am Stück als Paket an. 1 Paket = 1 Kommando oder > Antwort. Ich frage mich, warum Du bei solch simplen Kommandos wie "Licht an" Kilobytes an Daten schicken willst.... Im wesentlichen ist das jedoch korrekt. > 7) Der Einzige Fehler, auf den meine Anwendung reagieren muss, sind > Timeouts. Und selbst das kann unter Umständen entfallen, nämlich dann, > wenn die gesendeten Daten nicht wichtig waren oder ein > Wiederholmechanismus außerhalb der Anwendung existiert. Jepp. > Dann wäre UDP ja viel einfacher zu verwenden, als TCP. Oder nicht? Natürlich. UDP ist viel einfacher. Vergleiche es mit der Post: Brief in den Briefkasten und fertig. Umgekehrt regelmäßig den eigenen Briefkasten leeren. Wenn zwischendurch der Briefbote verunglückt mit Deinem Brief: Pech gehabt. > Ich habe noch nie UDP verwendet. C/C++ kann es ganz sicher, wie sieht es > mit Java aus? Da kenne ich nur Streams. Geht in Java selbstverständlich auch. https://systembash.com/a-simple-java-udp-server-and-udp-client/ Google hätte Dir das aber auch im Bruchteil einer Sekunde beantworten können.
:
Bearbeitet durch Moderator
Der entscheidende Punkt ist was damit uebertragen werden soll. Kann ich es mir leisten ein paar Nachrichten zu verlieren, oder eben nicht. Wenn ich ein File uebertrage muss es vollstaendig sein, sonst ist es wertlos. Also TCP. Wenn man Sound oder Video uebertraegt, machen ein paar fehlende Nachrichten nichts aus. Anders herum, uebertraegt man Zustaende oder Zustandsaenderungen? Wenn man Zustaende uebertraegt, zB Pegelmesser Daten, ist ein fehlendes Packet egal. Wenn man hingegen Zustandswechsel uebertraegt, wie "Taste wurde gedrueckt". geht etwas verloren. Daher kann man die Antwort nicht pauschalisieren, und die Ansaetze nicht gegeneinander ausspielen. In einem gewissen hat man Spielraum. Wenn man aus Sicherheitsgruenden einen Zustandswechsel nicht verpassen will, kann man ja Zustaende uebertragen, und der Empfaenger muss dann selbst den Wechsel herausfinden. Bedingt dann moeglicherweise eine hoehere Datenrate, resp mehr Meldungen auf dem Bus, weil man Redundanz uebertraegt. Da sind wir dann beim Thema, "hat das Protokol einen Zustand, oder nicht". Ich tendiere zu zustandsfreien Protokollen. Allerdings dann Master-Slave. Zustandsfrei bedeutet es gibt keinen impliziten Zustand, auf dem die Meldungen aufbauen. Der Master fraegt dann die Slaves periodisch ab. Und wird so ueber einen Zustand informiert, der Master uss sich nichts merken, und kann neu gestartet werden, ohne Konsequenz. Wenn man die Bandbreite hat...
:
Bearbeitet durch User
Oder D. schrieb: > Wenn ich ein File uebertrage muss es vollstaendig sein, sonst ist es > wertlos. Also TCP. Das ist nicht unbedingt zwingend, aber natürlich bequem. Die Prüfung auf Vollständigkeit kann man auch auf der Anwendungsschicht machen. Es gibt zum Beispiel diverse VPN-Tunnel, welche (auch aus Geschwindigkeitsgründen) mit UDP arbeiten. Im Tunnel selbst ist aber auch TCP möglich, obwohl es technisch über UDP transportiert wird.
:
Bearbeitet durch Moderator
Stefan U. schrieb: > 3) Gesendete Pakete bis maximal 1KB werden nie zerstückelt. Unwahrscheinlich aber nicht garantiert!
Bruno schrieb: > Stefan U. schrieb: >> 3) Gesendete Pakete bis maximal 1KB werden nie zerstückelt. > > Unwahrscheinlich aber nicht garantiert! Ach ja, und die Reihenfolge in der die Pakete ankommen ist auch nicht garantiert.
Danke für Deine Anregungen. Ihr habt mir damit gut geholfen, meine Gedanken zu sortieren. > Was hast Du eigentlich vor? Überlegen, ob es sich für mich lohnt, mich mit UDP zu beschäftigen. Ist ja nur ein Hobby, aber ich habe auch Familie. > aber Hauptsache IoT im Titel stehen :rolleyes: Mir war nichts intelligenteres eingefallen. > µC erkennt nicht auf welchem Port UDP ankommt, sonder muß dort lauschen Ja, soweit ich das bei µIP gesehen habe, muss er auf einem bestimmten Port lauschen. Das scheint mir aber kein Hindernis zu sein. > Ich frage mich, warum Du bei solch simplen Kommandos wie "Licht an" > Kilobytes an Daten schicken willst.... Will ich ja gerade nicht. Die 1KB hatte ich genannt, weil mir kein Anwendungsfall einfällt, wo ich mehrere KB am Stück senden würde. > Wenn man hingegen Zustandswechsel uebertraegt, wie "Taste > wurde gedrueckt". geht etwas verloren. Ja logisch. Bisher hatte ich fast immer Befehle gesendet und auf Antwort gewartet. Da würde ich dann ggf. den Befehl nochmal wiederholen. Bei TCP habe ich bisher auch Wiederholungen vorgesehen, allerdings auf einer neuen Verbindung (und daher Aufwändiger). > Ich tendiere zu zustandsfreien Protokollen. Allerdings dann Master-Slave. Ich auch. Ich bemerke nun, dass ich TCP regelrecht missbraucht habe - das einfachere UDP wäre besser geeignet gewesen. > Die Reihenfolge in der die Pakete ankommen ist auch nicht garantiert. Heisst in der Praxis: Wenn ich "LICHT AN" sende und direkt danach "LICHT AUS", könnte das Ergbnis sein, dass das Licht am Ende ungewollt an ist. Man könnte Sequenznummern hinzufügen, so dass der Empfänger veraltete Kommandos ignoriert. Wobei das ja wieder eine Funktion von TCP ist ... Darüber denke ich nochmal nach. Was mir erst durch die Diskussion so richtig bewusst geworden ist: Eine TCP Verbindung ist kaum mit einer Modem Verbindung vergleichbar. Beim Modem können gesendete Zeichen unterwegs verloren gehen, obwohl die Verbindung noch besteht. Bei TCP ist das nicht der Fall. Das habe ich nicht bedacht, deswegen habe ich meine TCP Anwendungen bsiher unnötig kompliziert gemacht. Der Wechsel zu UDP wird mir sicher sehr leicht fallen.
Die nicht garantierte Reihenfolge beim TCP hat etwas mit dem Routing zu tun. Langdistanzverbindungen koennen theoretisch ueber verschiedene Wege gehen, wenn einer der Wege verstopft ist. Sofern die Infrastruktur das kann. Nennt sich loadbalancing am Router. Das Ganz ist allerdings fuer zuhause uninteressant, denn diese Funktionalitaet ist schlicht nicht vorhanden. Und ja, das TCP arbeitet mit Sequenznummern. Deswegen ist es auch leichter auszutricksen, resp zu blockieren. Denn der Empfaenger muss alle Packete mit nicht in die Reihe passenden Sequenznummern buffern bis sie an die Reihe kommen. Wenn ich also eine Meldung schicke mit Sequenznummern 1,2,3,4,5,10, und dann abbreche, ist diese Verbindung offen und blockiert, er wartet auf Packete 6,7,8,9. Wie lange weiss ich nicht, ein Timeout. Wieviele gleichzeitigen Verbindungen pro Client akzeptiert der Server ? 10, 100 ? Irgendwann ist das Memory voll.
:
Bearbeitet durch User
Oder D. schrieb: > Denn der Empfaenger muss > alle Packete mit nicht in die Reihe passenden Sequenznummern buffern bis > sie an die Reihe kommen. muss? Er kann sie auch einfach verwerfen und behaupten er hat sie nicht bekommen. Dann muss der Client sie neu versenden. Das ist viel mehr ein Frage vom Puffer im Client, dann er muss jedes Paket noch speichern, wenn er keine Empfangsquittung hat.
UDP ist deutlich einfacher wenn alle Daten in eine Message reinpassen und verlorene Messages das System nicht durcheinander bringen. Die Messagegrösse ist OS abhänging und kann auch über mehrere Frames gehen, aber das Limit wird hier uIP sein wenn du das verwenden willst. Im heimischen Netz gehen auch keine Messages verloren, das passiert meiner Erfahrung nach wenn ein Sender extrem schnell sendet und der Empfänger nicht nachkommt wg. z.B. zuwenigen Buffern bei zu langsamer Verarbeitung. Aber so CM3 MCUs mit NIC wie LPC1769 machen da locker 1 ms Zyklus mit. Beim uIP ist die UDP Implementierung nicht so toll. Schnell schon, da passiert ja nicht viel. Aber ich wollte zB so ein recvfrom(), also auf einem Port lauschen und von beliebiger Adresse empfangen und dem Sender Antworten zurückschicken. Das konnte uIP nicht weil die Senderadresse nicht gespcheichert wird. Da der Stack aber recht überschaubar ist lässt sich sowas nachträglich einbauen. An der Stelle wollte ich mich immer mal mit lwIP beschäftigen, das soll besser sein und die CM3 haben alle genug Power dafür.
Jojo S. schrieb: > UDP ist deutlich einfacher wenn alle Daten in eine Message reinpassen > und verlorene Messages das System nicht durcheinander bringen. Die > Messagegrösse ist OS abhänging und kann auch über mehrere Frames gehen, > aber das Limit wird hier uIP sein wenn du das verwenden willst. Im > heimischen Netz gehen auch keine Messages verloren, das passiert meiner > Erfahrung nach wenn ein Sender extrem schnell sendet und der Empfänger > nicht nachkommt wg. z.B. zuwenigen Buffern bei zu langsamer > Verarbeitung. Aber so CM3 MCUs mit NIC wie LPC1769 machen da locker 1 ms > Zyklus mit Na dann, fröhliches pfuschen.
> Beim uIP ist die UDP Implementierung nicht so toll
Ja habe ich auch schon bemerkt. Allerding traue ich mir zu, ein
minimalistisches UDP Protokoll selbst zu entwickeln.
Einfach mal schauen, was es so an Protokollen gibt. Recht verbreitet und immer stärker zunehmend sind derzeit MQTT und CoAP, das erst arbeitet auf TCP, das zweite mit UDP. https://eclipse.org/community/eclipse_newsletter/2014/february/article2.php http://iot.eclipse.org/standards
ich geh sogar noch weiter, und wickel es über broadcast ab... ich sende ein datenpäckl mit dem zustand den ich gerne am aktor xy sehen würde, und dieser sendet mir den aktuellen status zurück wenn er den befehl ausgeführt hat. das hat den luxusvorteil, das alle zur steuerung gehörende geräte eine statusänderung mitbekommen und ggf anzeigen können, und ich nicht nur weiß, dass der befehl angekommen ist, sondern auch ausgeführt wurde. so brauch man sich auch keine gedanken machen, wenn ein gerät mal eine andere IP zugewiesen bekommt. funktioniert logischer weise nur in lokalen netzwerken und mit kniffen max. noch im VPN...
Steven M. schrieb: > das hat den luxusvorteil, das alle zur steuerung gehörende geräte eine > statusänderung mitbekommen Wer garantiert das das alle mitbekommen? IP auf SOCs scheint grundsätzlich Pfusch zu sein, selbst die ASICs und FPGAs in den Monstern von Juniper und Cisco sind total pfuschig und verbuggt.
Profi schrieb: > Steven M. schrieb: >> das hat den luxusvorteil, das alle zur steuerung gehörende geräte eine >> statusänderung mitbekommen > > Wer garantiert das das alle mitbekommen? > Niemand, deswegen ist es ein luxusvorteil... Wenn ein gerät es genau wissen will, weil eine entscheidung ansteht, kann man den status des zielgerätes ja abfragen... Bei einem außentemperaturfühler zB, der alle 5 minuten die temperatur ins netzwerk brüllt, ist es unerheblich, ob alle anzeigen jede meldung mitbekommen, oder nur jede zweite Ein aktor der temperaturabhängig schalten muss, fragt die temp halt explizit ab...
Steven M. schrieb: > Niemand, deswegen ist es ein luxusvorteil... > Wenn ein gerät es genau wissen will, weil eine entscheidung ansteht, > kann man den status des zielgerätes ja abfragen... > > Bei einem außentemperaturfühler zB, der alle 5 minuten die temperatur > ins netzwerk brüllt, ist es unerheblich, ob alle anzeigen jede meldung > mitbekommen, oder nur jede zweite > > Ein aktor der temperaturabhängig schalten muss, fragt die temp halt > explizit ab... Geile Sematik.
Bruno schrieb: > Stefan U. schrieb: >> 3) Gesendete Pakete bis maximal 1KB werden nie zerstückelt. > > Unwahrscheinlich aber nicht garantiert! UDP sendet Datagramme. Diese können bis knapp 64k lang sein. Und sie werden dem Anwederprogramm als ganzes geliefert. Immer! Das hat nichts mit den Ethernetframes zu tun. Ist das Datagramm kürzer als eine MTU wird es auch als ganzes in einen Ethernetframe gepackt, es kann ja keinen angefangenen Frame geben, in dem noch Platz für neue Daten ist. MfG Klaus
Klaus schrieb: > UDP sendet Datagramme. Diese können bis knapp 64k lang sein. Und sie > werden dem Anwederprogramm als ganzes geliefert. Immer! Das hat nichts > mit den Ethernetframes zu tun. Ist das Datagramm kürzer als eine MTU > wird es auch als ganzes in einen Ethernetframe gepackt, es kann ja > keinen angefangenen Frame geben, in dem noch Platz für neue Daten ist. Fragmentiertes UDP wird aufwendiger und glaube nicht das die üblichen IP-Stacks für damit klarkommen. Aber die Idee ist gut, man könnte die Dinger mit unvollständigen Fragmenten beschießen, mal sehen wie lange die damit klarkommen.
Es gibt keine enfache Daumenregel. Mal ist TCP sinnvoll, mal UDP. Die Art der Kommunikation einer Anwendung bestimmt, was sinnvoller ist. So sollte man auch berücksichtigen, inwieweit höhere Layer der Kommunikation ebenfalls Retries durchführen - das kann beispielsweise passieren, wenn man Anwendungen von anderen Übertragungsarten auf TCP/IP portiert.
A. K. schrieb: > Es gibt keine enfache Daumenregel. Mal ist TCP sinnvoll, mal UDP. Genau so ist das. Deswegen gibt es ja überhaupt diese zwei Protokolle, denn wenn eins davon für alle Zwecke das geeignetste wäre, bräuchte es ja auch nur dieses eine zu geben und das Problem der Auswahl würde sich erst garnicht stellen...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.