Wie Objekt per Sockets übertragen?



  • Hiho,

    ich bastel grade an einem kleinen Netzwerkkartenspiel, dass hinterher mal als Client-Server-Anwendung laufen soll.

    Die Verbindung zwischen den Sockets von Client und Server steht schon, aber ich habe ein Problem damit dann konkrete Daten (z.B. Objekte der Klasse Karte) zu übertragen.

    Meine Sendefunktion schaut bisher so aus:

    void Server::sendData(Karte* karte){
        int sendedBytes;
        sendedBytes=send(inputsocket1,(const char*)karte,sizeof(*karte),0);
        cout << "sendedBytes: " << sendedBytes;
    }
    

    und bei der Empfangsfunktion bin ich sehr unschlüssig wie das aussehen muss.

    Wie mach ich das denn am Besten?
    Ich bin im Netz auf folgende Möglichekiten gestoßen:
    1. auf Empfängerseite ein bisschen rumzucasten
    2. auf eine externe lib wie boost zurückgreifen und serialisierung zu benutzen
    3. nur Attributwerte übertragen und beim Empfänger damit ein neues Element initialisieren



  • 1 wenn Karte ein POD ist (#pragma pack(1) nicht vergessen), ansonsten eher 3.



  • Du castest karte nach char*, das ist nie eine gute Idee. Gerade kürzlich in einem anderen Thread wird erklärt warum: http://www.c-plusplus.net/forum/311715

    Es bezieht sich zwar auf das Speichern in einer Datei, was aber grundsätzlich gleiche Probleme hat wie eine Netzwerkkommunikation.



  • @butterbemme
    Die "sauberste" Lösung ist alles brav zu serialisieren. Ob jetzt mit Hand oder einer Serialisierungs-Library ... Geschmackssache würde ich sagen.
    Bzw. je komplexer die Datenstrukturen werden, desto eher würde ich ne fertige Library empfehlen.



  • Du solltest dich denke ich gleich von dem Gedanken verabschieden, ein "Objekt" über das Netzwerk zu schicken. Das Problem ist einfach, dass Server und Client auf sehr unterschiedlichen Architekturen laufen können. Du kannst dich hier auf nichts verlassen: Alignment, Padding, Enianess. Du wirst nicht umher kommen in deinem Protokoll "Typen" zu definieren, und das auf Byte Ebene, für die du dann genau festlegst, wie sie gesendet werden. Das ist dann die Vereinbarung für Client und Server, so haben die Nachrichten auszusehen. Wie genau die Gegenseite das dann implementiert, wird irrelevant.
    Und damit du jetzt nicht verwirrt wirst: Das hat nichts mit Code zu tun. Dein Protokoll ist einfach nur eine Beschreibung des Ablaufs, den du festlegst. Mal ein Beispiel:

    All data is send in little endian byteorder.
    
    Map:
      uint16 width
      uint16 height
      uint8 data[width * height]
    


  • Och man kann auch einfach textbasierte Protokolle verwenden. Hat viele Vorteile, z.B. was Debugging angeht. Und wenn man das Format passend auslegt auch was Erweiterbarkeit angeht. XML ist z.B. keine dumme Idee. JSON wäre auch nicht ganz doof.



  • Jau, textbasiert geht latürnich auch. Ich hätte das "Byteebene" nicht so betonen sollen. Ich meine damit nur, dass er (ohne Informationen über Compiler, System etc.) nicht wissen kann wie die Objekte im Speicher angeordnet sind, und er das deshalb selbst im Protokoll definieren muss, da ist das "Byteebene" irgendwie dazwischen gerutscht. :xmas1:



  • Danke für eure Antworten
    ich hab mich jetzt vorerst für Möglichkeit 3 entschieden und schau mal wies damit läuft



  • Wenn Du das erste Mal einen Tisch per Socket überträgst und nicht bloß den Bauplan, dann melde Dich bitte bei mir, bevor Du an die Öffentlichkeit gehst!



  • Protocol Buffers? Wäre imho noch das beste, wenn es denn ein Binärformat sein soll. Hat zum Debuggen auch eine lesbare Textrepräsentation.

    Das Boost::Serialization-Zeug wird sich ja eher nicht so richtig für sowas eignen, oder? Gibt es da schmerzfreie Wege das auf der anderen Seite ohne C++ und Boost wieder zu dekodieren? Auf allen Endpunkten auf C++ beschränkt zu sein, ist für ein Netzwerkprotokoll ja nicht sonderlich toll. Viele Features der Serialization-Library sind hier ja auch gar nicht nötig.

    Unterstützung für Protocol Buffers gibt es für zahlreiche Sprachen/Systeme und das On-Wire-Format ist relativ simpel.


Anmelden zum Antworten