Sockets TCP/IP wieviel auf einmal empfangen/senden



  • Wieviel Bytes kann man auf einmal mit send über ne Socketverbindung schicken um dann sicher zu sein, dass man sie mit einem recv empfangen kann. Ist das irgendwo definiert?

    Kann man z.b. Sicher sein, dass das immer funktioniert?

    client.send("start")

    txt = server.recv() -> txt = "start"

    Oder kann es auch bei so wenig Daten sein, dass man zwei mal server.recv() aufrufen muss um alles zu bekommen?



  • TCP hat normalerweise eine maximale "Window size" von 65 535 byte. Aber iirc gibt es Erweiterungen, die das deutlich erhöhen. Ansonsten hängt das auch vom Betriebssystem ab. Auf POSIX Systemen findest du in limits.h eine Konstante PIPE_BUF, die angibt wie groß ein Buffer maximal sein darf, damit die Schreiboperation atomar ist (unter Linux sind das idR 4096 bytes). Und dann gibt es natürlich noch so etwas wie TCP_CORK, um den Kernel daran zu hindern Pakete "zu früh" zu verschicken.

    http://baus.net/on-tcp_cork

    edit: aber man sollte immer damit rechnen, dass die Daten zerstückelt ankommen oder send sie nicht in einem Stück schickt :).



  • socke schrieb:

    Wieviel Bytes kann man auf einmal mit send über ne Socketverbindung schicken um dann sicher zu sein, dass man sie mit einem recv empfangen kann. Ist das irgendwo definiert?

    nö, du kannst fast 'beliebig viel' schicken. send hat erstmal 'nen fetten puffer dahinter und der rückgabewert gibt dir an, wieviel von deinen daten send geschluckt hat. wenn du z.b. 100 bytes schickst und der rückgabewert ist 80, dann weisste, dass du die hinteren 20 bytes nochmal senden musst (nach einer kleinen pause z.b, wenn wieder platz im puffer ist).

    socke schrieb:

    txt = server.recv() -> txt = "start"
    Oder kann es auch bei so wenig Daten sein, dass man zwei mal server.recv() aufrufen muss um alles zu bekommen?

    ja, die daten können zerstückelt sein.
    🙂



  • rüdiger schrieb:

    TCP hat normalerweise eine maximale "Window size" von 65 535 byte.

    naja, die 'window size' ist variabel und gibt an, wieviele bytes ein TCP senden darf, bevor es ein 'ack' von der anderen seite erwarten darf (TCPs interne flusskontrolle). mit der menge der daten, die man in einen socket schieben kann, hat es nur indirekt zu tun. wenn z.b. ein socket langsamer ausgelesen wird, als die gegenstelle sendet, dann verringert das empfänger-TCP seine 'window size', damit der andere ihm nicht zu viel schickt. als folge davon läuft der buffer des senders voll, das wirkt sich auf den rückgabewert von 'send' aus, d.h. die anwendung wird dazu gezwungen, langsamer zu senden.
    🙂



  • ;fricky schrieb:

    rüdiger schrieb:

    TCP hat normalerweise eine maximale "Window size" von 65 535 byte.

    naja, die 'window size' ist variabel und gibt an, wieviele bytes ein TCP senden darf, bevor es ein 'ack' von der anderen seite erwarten darf (TCPs interne flusskontrolle). mit der menge der daten, die man in einen socket schieben kann, hat es nur indirekt zu tun. wenn z.b. ein socket langsamer ausgelesen wird, als die gegenstelle sendet, dann verringert das empfänger-TCP seine 'window size', damit der andere ihm nicht zu viel schickt. als folge davon läuft der buffer des senders voll, das wirkt sich auf den rückgabewert von 'send' aus, d.h. die anwendung wird dazu gezwungen, langsamer zu senden.
    🙂

    Ja, da hast du Recht. Ich wollte nur andeuten, dass das Aussehen der Paketen von vielen Faktoren abhängt.



  • Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?



  • socke schrieb:

    Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?

    nee, es gibt noch andere gründe, warum die daten zerstückelt werden können. du kannst nie davon ausgehen, dass "start" in einem stück ankommt. TCP behandelt die bytes als datenstrom. wenn du alles am stück brauchst (warum eigentlich?), dann verwende UDP, da wird nichts gestückelt. naja, zumindest nicht bei kleinen paketen, bei grossen, die über der MTU des netzwerkes liegen, haste dann IP-fragmentierung (wovon du aber wohl nix merken wirst, weil ein UDP socket dir nur vollständige pakete gibt).
    🙂



  • socke schrieb:

    Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?

    Rechne einfach immer damit, dass die Daten zerstückelt ankommen.

    ;fricky schrieb:

    dann verwende UDP, da wird nichts gestückelt.

    Nur wenn man Pech hat, kommt gar nichts an oder die Daten in falscher Reihenfolge :).



  • ;fricky schrieb:

    socke schrieb:

    Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?

    nee, es gibt noch andere gründe, warum die daten zerstückelt werden können.

    Welche?



  • rüdiger schrieb:

    ;fricky schrieb:

    dann verwende UDP, da wird nichts gestückelt.

    Nur wenn man Pech hat, kommt gar nichts an oder die Daten in falscher Reihenfolge

    stimmt, wobei bytes innerhalb von paketen nicht vertauscht werden, d.h. wenn er 'hallo' sendet, kommt es entweder vollständig und in richtiger reihenfolge, oder garnicht an.

    socke schrieb:

    ;fricky schrieb:

    socke schrieb:

    Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?

    nee, es gibt noch andere gründe, warum die daten zerstückelt werden können.

    Welche?

    verschiedene, z.b. könnte sich tcp entschliessen kleinere paket zu senden, weil die verbindung schlecht ist, oder es schickt pakete mit nur einem einzelnen nutzdaten-byte als probes, weil die gegenstelle 'window size=0' gemeldet hat. bestimmt gibts noch ein paar gründe mehr. langer rede kurzer sinn: du kannst *niemals* davon ausgehen, dass TCP dir die daten nicht auseinanderfleddert. ausser du implementierst ein eigenes TCP, dass nie weniger als x bytes sendet (oder du schaust mal, welche QoS-einstellungen dein system bietet).
    🙂



  • ;fricky schrieb:

    socke schrieb:

    ;fricky schrieb:

    socke schrieb:

    Die Nachricht wird also immer nur dann zerstückelt, wenn sie nicht mehr in den Puffer bzw. die "window size" passt. client.send("start") sollte also immer ganz ankommen, wenn ich vorher alles ausgelesen hab. Stimmt das so oder gibts da noch andere Fälle?

    nee, es gibt noch andere gründe, warum die daten zerstückelt werden können.

    Welche?

    verschiedene, z.b. könnte sich tcp entschliessen kleinere paket zu senden, weil die verbindung schlecht ist, oder es schickt pakete mit nur einem einzelnen nutzdaten-byte als probes, weil die gegenstelle 'window size=0' gemeldet hat. bestimmt gibts noch ein paar gründe mehr. langer rede kurzer sinn: du kannst *niemals* davon ausgehen, dass TCP dir die daten nicht auseinanderfleddert. ausser du implementierst ein eigenes TCP, dass nie weniger als x bytes sendet (oder du schaust mal, welche QoS-einstellungen dein system bietet).
    🙂

    Ich hab jetzt schon ne Weile mit der einfachen Send->Recv Methode gearbeitet und es hat eigentlich immer gut funktioniert bei kurzen Befehlen, nur ne große Datei ging es so nicht, da musste ich die größe mit senden und dann solange lesen bis alles da war. Hat das bei den kurzen Befehlen so gut funktioniert, weil ich nur im LAN war? Gibts eigentlich kein einfaches Protokoll bei dem man auf nichts aufpassen muss? Einfach nur send->recv und dann ist alles da, oder timeout.



  • ^^wieso ist das stückeln für dich ein problem? TCP ist nunmal nicht echtzeitfähig, dafür stellt es aber einiges an, damit daten sicher ankommen. eine einfache methode wäre z.b.: verbindung aufmachen - kommunizieren - verbindung schliessen. ein erfolgreiches schliessen der verbindung (das mit beiderseitigem einverständnis geschieht), bedeutet für beide partner mit, dass alles angekommen ist.
    🙂



  • ;fricky schrieb:

    ^^wieso ist das stückeln für dich ein problem?

    Weil ich mit halben Befehlen nix anfangen kann.

    TCP ist nunmal nicht echtzeitfähig, dafür stellt es aber einiges an, damit daten sicher ankommen. eine einfache methode wäre z.b.: verbindung aufmachen - kommunizieren - verbindung schliessen. ein erfolgreiches schliessen der verbindung (das mit beiderseitigem einverständnis geschieht), bedeutet für beide partner mit, dass alles angekommen ist.

    Wieso schliessen? Ich schick nen Befehl und warte auf Antwort, wenn die nicht innerhalb einer bestimmten Zeit kommt, hat es nicht funktioniert und dann kann ich abbrechen. Sind keine lebenswichtigen Daten die da gesendet werden.



  • socke schrieb:

    ;fricky schrieb:

    ^^wieso ist das stückeln für dich ein problem?

    Weil ich mit halben Befehlen nix anfangen kann.

    keine sorge, der rest kommt ja auf jeden fall nach kurzer zeit hinterher.
    🙂



  • socke schrieb:

    ;fricky schrieb:

    ^^wieso ist das stückeln für dich ein problem?

    Weil ich mit halben Befehlen nix anfangen kann.

    Ja dann lies halt ganze Befehle um Himmels willen!
    Ich check echt nicht was alle immer ein Problem damit haben, dass TCP/IP ein Byte-Stream ist, und nicht ein Message-Stream.
    Ist doch genau dasselbe wie wenn du von Standard-In liest und nach Standard-Out schreibst.

    nur ne große Datei ging es so nicht, da musste ich die größe mit senden und dann solange lesen bis alles da war

    Rate mal was: 💡 das gleiche System kannst du mit kleinen Datenstücken auch verwenden. 💡



  • hustbaer schrieb:

    socke schrieb:

    ;fricky schrieb:

    ^^wieso ist das stückeln für dich ein problem?

    Weil ich mit halben Befehlen nix anfangen kann.

    Ja dann lies halt ganze Befehle um Himmels willen!
    Ich check echt nicht was alle immer ein Problem damit haben, dass TCP/IP ein Byte-Stream ist, und nicht ein Message-Stream.
    Ist doch genau dasselbe wie wenn du von Standard-In liest und nach Standard-Out schreibst.

    Machst du da auch ne Schleife rum, um nen String zu lesen bzw. schreiben?

    nur ne große Datei ging es so nicht, da musste ich die größe mit senden und dann solange lesen bis alles da war

    Rate mal was: 💡 das gleiche System kannst du mit kleinen Datenstücken auch verwenden. 💡

    Ach ne 🙄







  • Machst du da auch ne Schleife rum, um nen String zu lesen bzw. schreiben?

    das stichwort heißt kapseln.



  • Benutz doch sctp. Das schickt Pakete wie Udp und sichert vore deren Verlust und deren Reihenfolge wie TCP.


Log in to reply