Ein paar Fragen zu recv () und send ()



  • Hi!

    Ich will für ein Projekt ein Protokoll implementieren und hab dazu ein paar Fragen zu recv (). Ein simples "Paket" aus dem Protokoll sieht in etwa so aus:

    ID     4 Bytes
    Size   4 Bytes
    Data   `Size` Bytes
    

    Da ich nicht weiß, wie groß jedes Paket im Endeffekt ist, kann ich also auch nicht im voraus eine Buffer-Größe festlegen. Wäre jetzt so was wie:

    uint32_t id, size;
    assert (recv (s, &id, 4, 0) == 4);
    assert (recv (s, &size, 4, 0) == 4);
    char *buf = new char [size];
    recv (s, buf, size, 0);
    

    möglich? Oder macht da recv () (Performance- ?)Probleme, wenn ich erstmal einzelne Bytes und dann den Rest aus der Queue ziehen will? Oder gibts da noch irgendwelche Probleme mit der Fragmentierung von IP/TCP?

    Betreffs Fragmentierung hab ich auch eine Frage zu send (). Dafür hab ich zwei Beispiele:
    1. ein Paket mit z. B. einer Chat-Nachricht (2000 Bytes)
    2. ein Paket mit einer simplen Nachricht an den Client (20 Bytes)
    Das erste Paket wird doch von TCP in `MSS`-große Segmente zerlegt und diese dann einzeln versendet. Wenn ich jetzt mein zweites Paket so schnell danach abschicke, dass die Bestätigung für das erste noch nicht da ist, wird dann das zweite Paket an das zweite Segment des ersten Paketes angehangen? Oder wird für da für jedes send () garantiert ein eigenes IP/TCP-Paket erzeugt?
    Und was ist, wenn der Großteil der Pakete aus nur 16 Bytes bestehen würde? Würde dann auch für jedes Paket ein eigenes IP/TCP-Paket versendet werden? Wäre doch ein bisschen Overkill, oder?



  • Zu dem ersten Teil: Ja, du kannst erst ID+Size empfangen und hinterher die Daten, das ist sinnvoll. Nicht sinnvoll dagegen sind die asserts (asserts sollen nur Logikfehler aufdecken, kein unerwartetes aber spezifiziertes Verhalten) und die fehlende Überprüfung der Rückgabewerte auf 0 (=Verbindung geschlossen) oder -1 (=Fehler) oder <4 (=Noch nicht alles da). Alles in allem würde ich dir empfehlen, nicht die Empfangs-Schleifen-Routinen mit Exception-Handling und allem selber zu schreiben, sondern dich auf gute und schlanke Bibliotheken zu verlassen (boost::asio ist schwierig zum Lernen aber sehr umfangreich, SFML ist einfach zu lernen und kapselt die Sockets im Prinzip nur in Klassen).

    Zum zweiten Teil: Ich weiß es nicht. Ich weiß aber, dass es dir als Programmierer egal sein kann, weil die Socket-Verbindung wie ein Strom funktioniert, nicht wie die Post paketweise. D.h. du lässt sowas alles die darunterliegenden Schichten erledigen und kümmerst dich nur um die korrekte Implementation des Protokolls und allem was dazugehört 🙂



  • Zum ersten Teil: Das war nur Pseudo-Code, der verdeutlichen sollte, was ich vor habe.
    Zum zweiten Teil: Das ist gut. 😃 Hab grade noch was zum Nagle-Algo und TCP_CORK gefunden, ich denke mal, das wird reichen.

    Thx. 🙂


Anmelden zum Antworten