Hallo, ich habe NULL Erfahrungen mit übertragungen über Netzwerk-Sockets per TCP/IP. Deshalb hab ich ein paar Fragen. Ich möchte Kommandos + Parameter übertragen. Das ganze soll unter Linux passieren. Es funktioniert im Prinzip schon. Also ich kann Sockets auf Sender und Empfängerseite öffnen, die Verbindung kommt zustande (connect) und ich kann Daten übertragen. Meine Frage ist nun, angenommen die Paketlänge ist konstant. Kann ich auf der Empfängerseite solange fread(...) aufrufen, bis die erwartete Byteanzahl empfangen wurde? So mache ich es im Moment und es funktioniert auch auf meinem Tisch. Kann der Emfänger nicht asynchron werden? Also mittem im Paket aufsetzen (wodurch auch immer) und dann synchronisiert sich der Empfänger nie wieder. Oder passiert das nicht? Also das Paket, was mit einer Länge sagen wir 4kB abgeschickt wurde, kommt auch so an? Ich denke ich muß da auch Timeouts über select() implementieren in der Schleife, die per fread() die Daten einsammelt. Und dann neu aufsetzen, falls was schief geht. Und dann kommt das nächste Problem. Nach einem Timeout muß ich ja an der richtigen Stelle aufsynchronisieren, also am Paketanfang. Also erstmal eine eindeutige Kennung empfangen und dann weiter? Durch die Defragmentierung kommen die Daten ja auch nicht in einem Rutsch an sondern sie kommen evtl. in kleinen Häppchen. Vielleicht denke ich auch viel zu kompliziert und es ist alles ganz einfach. Hab noch nie damit gearbeitet und deshalb diese Fragen. Über Antworten freue ich mich, danke. 900ss
TCP stellt Dir einen verläßlichen Byte-Stream zur Verfügung. Hab' Vertrauen, die meisten TCP/IP-Software-Stacks sind bereits gut gereift. Die Aufteilung in Pakete mußt Du selbst machen, z.B. durch eine Längenangabe am Anfang eines jeden Pakets. Wenn irgendetwas außer Tritt gerät, dann ist das mit 99,999%iger Wahrscheinlichkeit ein Programmierfehler bei Dir. Den reparierst Du akut durch Abbrechen und Neuverbinden und mittelfristig durch Korrektur Deines Programms. Wenn es TCP tatsächlich nicht gelingt, zu tun, wofür es da ist, dann wird read/write was auch immer mit einem 0 gelesenen/geschriebenen Bytes zurückkommen und in errno oder sonstwo wird ein Fehlerkode stehen, das hängt an der verwendeten Bibliothek. Und dann hilft natürlich auch ein Neuaufbau der Verbindung.
TCP kümmert sich automatisch um Retransmits von verlorengegangen oder bei der Übertragung verfälschten und die Beseitigung von ggf. doppelt angekommenen Paketen. Weiterhin sorgt es auch dafür, dass alle Daten genau in der Reihenfolge ankommen, in der sie auch gesendet wurden. Es garantiert dagegen nicht, dass die Blöcke, in denen die Daten empfangen werden, genau so aufgeteilt sind, wie sie gesendet wurden. Anders gesagt: TCP ist Stream-orientiert. Alle Bytes, die gesendet wurden, kommen genau in der Reihenfolge und Anzahl auch wieder an, so lange die Verbindung nicht abgebaut wird oder abreißt. 900ss D. schrieb: > Meine Frage ist nun, angenommen die Paketlänge ist konstant. Kann ich > auf der Empfängerseite solange fread(...) aufrufen, bis die erwartete > Byteanzahl empfangen wurde? So macht man das normalerweise. Allerdings eher mit read() oder recv(). fread gehört eigentlich eher zur Standard-C-Schnittstelle für Dateioperationen über FILE*. > Kann der Emfänger nicht asynchron werden? Also mittem im Paket aufsetzen > (wodurch auch immer) und dann synchronisiert sich der Empfänger nie > wieder. Oder passiert das nicht? Nein. > Also das Paket, was mit einer Länge sagen wir 4kB abgeschickt wurde, > kommt auch so an? Es kommt nicht unbedingt als genau ein 4kB-Paket wieder an, aber alle Bytes kommen wieder genau so an, und es kommt genau auf die vorher gesendeten Bytes folgend an. Daß zwischendrin mal was fehlt, kommt nicht vor. > Ich denke ich muß da auch Timeouts über select() implementieren in der > Schleife, die per fread() die Daten einsammelt. Und dann neu aufsetzen, > falls was schief geht. Und dann kommt das nächste Problem. Nach einem > Timeout muß ich ja an der richtigen Stelle aufsynchronisieren, also am > Paketanfang. Was willst du denn nach dem Timeout machen? Einfach nochmal lesen? Dann hättest du deinen Timeout ja einfach umgangen. Du musst schon die Verbindung komplett ab- und wieder neu aufbauen. Und damit bist du ja wieder am Anfang einer neuen Verbindung und alles ist ganz von selbst wieder aufsynchronisiert. > Durch die Defragmentierung kommen die Daten ja auch nicht in einem > Rutsch an sondern sie kommen evtl. in kleinen Häppchen. Richtig. Das wird durch dein wiederholtes Lesen abgedeckt.
:
Bearbeitet durch User
Oh danke euch beiden, das ging ja schnell :) diereinegier schrieb: > TCP stellt Dir einen verläßlichen Byte-Stream zur Verfügung. Hab' > Vertrauen, die meisten TCP/IP-Software-Stacks sind bereits gut gereift. Hehe, ohne Erfahrung Vertrauen zu haben ist für mich zumindest schwer :) Aber wirklich Zweifel hatte ich nicht. Hab nur lieber nochmal fragen wollen. Das ganze wird unter Linux laufen, soviel zum TCP/IP Stack. Rolf Magnus schrieb: > Allerdings eher mit read() oder recv(). > fread gehört eigentlich eher zur Standard-C-Schnittstelle für > Dateioperationen über FILE*. Ich nutze auch read(). Hatte mich vertan. Also dann mache ich im Prinzip schon alles richtig so wie ich es implementiert habe. was mir noch durch den Kopf geht, wenn man verschieden lange Pakete hat, dann wird man wohl erst ein Längenfeld senden und dann die Anzahl Bytes, die im Längenfeld stand. Oder gibt es bessere Lösungen? Und wie behandelt man eigentlich "schlechte" Verbindungen? Ich denke kann ja schonmal sein, dass die Verbindung sehr "stottert". Wenn das zu schlimm wird und abrechen will, dann muß man ja schon mit Timeout arbeiten. Wie lang macht man diese Zeiten sinnvollerweise? Ok, hängt sicher auch von der Anwendung ab.
:
Bearbeitet durch User
Wenn du im lokalen Netz agieren willst wäre UDP auch eine Option wenn du Paketorientiert arbeiten willst. Ansonsten gibt es ja schon soooo viel Fertige Protokolle warum also nicht mal schauen ob was für dich dabei ist? Wenn ich Linux lese würde sich doch ggf. sogar was High-Level anbieten wie HTTP...
Läubi .. schrieb: > Wenn du im lokalen Netz agieren willst wäre UDP auch eine Option wenn du > Paketorientiert arbeiten willst. Ist nicht lokales Netz, nur wenn es bei mir auf dem Tisch steht :) > > Ansonsten gibt es ja schon soooo viel Fertige Protokolle warum also > nicht mal schauen ob was für dich dabei ist? Wenn ich Linux lese würde > sich doch ggf. sogar was High-Level anbieten wie HTTP... Es war tatsächlich eine Überlegung, auf der einen Seite einfach einen Webserver laufen zulassen. Ich habe aber auch keine Ahnung, wie resourcenaufwendig bezüglich Übertragunsdatenmenge das Ganze bei einem Webserver ist. Dazu habe ich mir auch Node-Red von IBM angesehen. Das läuft ja sogar auf einem Rasp-PI. Aber das kommt jetzt vom Thema ab. Mich interessieren eher die Antworten auf meine Fragen oben.
Ja, header mit Länge ist die "Standardlösung" in dem Fall. Oder wenn die Daten es hergeben ein eindeutiges Trennzeichen (bei textbasierten Protokollen halt z.b. '\n') Oder halt fertige Lösungen, ich möchte da noch auf google Protocol Buffers oder deren "Nachfolger" Captn Proto verweisen.
900ss D. schrieb: > Es war tatsächlich eine Überlegung, auf der einen Seite einfach einen > Webserver laufen zulassen. Ich habe aber auch keine Ahnung, wie > resourcenaufwendig bezüglich Übertragunsdatenmenge das Ganze bei einem > Webserver ist. HTTP an sich ist sehr sparsam und auch sehr felxibel, du kannst im Notfall sogar die Daten zwischen Server/Client komprimieren. http://www.lighttpd.net/ wäre z.B. eine sehr leichtgewichtige Implementierung, wenn das Ziel ein "normales" Linux ist wäre Apache sicher auch möglich. Vorteil ist auch einfach: Du findest sehr viel Client-Libs die du nutzen kannst, und selbst ohne ist der Client-Part sehr einfach zu stricken im Notfall kannst du auf HTTP1.0 downgraden.
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.