<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Suche Implentierungsideen]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich kämpfe momentan mit einem - da bin ich mir eigentlich sicher- relativ banalem Problem. Irgendwie stehe ich aber auf dem Schlauch und bekomme nichts vernünftiges hin.<br />
Vielleicht hat ja von euch jemand eine zündende Idee <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Es geht um folgendes:<br />
Ich brauche eine Klasse, die UDP Datenpakete wrapped.<br />
Momentan habe ich das folgendermaßen aufgezogen:<br />
Meine Basisklasse enthält im Grunde nichts weiter als einen char*, den ich brauche um meine Daten später an SDLNet_UDP_Send weitergeben kann (benötigt seine Daten als char*)</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES

/// LOCAL INCLUDES

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
  class CUDPPacketData
  {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
        CUDPPacketData( ) 
            : mpData(0)
        {}

      /// Destructor
        virtual ~CUDPPacketData() {}

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      const char* BaseData() const { return mpData; }

      ///////////// MEMBERS
      char* mpData;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
  };

} // netCodeCommon
</code></pre>
<p>Davon leite ich mir meine UDP Paket Basisklasse ab, die als pure virtual Klasse die Interfaces zur Verfügung steht, die letztendlich von den Implentierungsklassen implementiert werden:</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES

/// LOCAL INCLUDES
#include &quot;UDPPacketData.hpp&quot;

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
  //template &lt;typename T = void&gt;
  class CUDPPacket : public CUDPPacketData
  {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
      CUDPPacket( )
      {
      }

      /// Destructor
      virtual ~CUDPPacket() { PacketReceived(); }

      ///////////// METHODS
      void PacketReceived()
      {
          if ( 0 != mpData )
              delete [] mpData;
      }

      ///////////// OPERATORS

      ///////////// ACCESSORS
      const char* PacketData() { return mpData; }
     // virtual const T* Data() const = 0;
      virtual const size_t DataLen() const = 0;
      virtual const size_t TotalLen() const = 0;
      virtual const int ID() const = 0;
      virtual void RestoreFromData(char* data) = 0;

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      int mID;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
  };

} // netCodeCommon
</code></pre>
<p>So, jetzt geht es ans Eingemachte.<br />
Ich habe für jede Aufgabe ein eigenes UDP Paket, ergo auch eine eigene Klasse.<br />
Nehmen wir mal exemplarisch meine Ping Klasse:</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES
#include &lt;netCode/common/UDPPacket.tpp&gt;
#include &lt;netCode/common/exception.hpp&gt;

/// LOCAL INCLUDES
#include &quot;UDPPacketIDs.h&quot;

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
    struct S_PingData
    {
        unsigned int magicNumber;
        bool reply;
    };

    class CUDPPing : public CUDPPacket // &lt;S_PingData&gt;, CAllocatableObject
    {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
      CUDPPing(char* data)
          : mID(Type_Ping) 
      {
          RestoreFromData(data);
      }

      CUDPPing(unsigned int magicNumber, bool reply)
          : mID(Type_Ping)
      {
          Init(magicNumber, reply);
      }

      /// Destructor
      virtual ~CUDPPing() { if ( 0 != mpData ) delete [] mpData; }

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      virtual const S_PingData* Data() const
      {
          return reinterpret_cast&lt;S_PingData*&gt;(mpData + sizeof(mID));
      }

      virtual const size_t DataLen() const { return sizeof(S_PingData); }
      virtual const size_t TotalLen() const { return sizeof(S_PingData) + sizeof(mID); }
      virtual const int ID() const { return mID; }
      virtual void RestoreFromData(char* data)
      {
          if ( 0 == data) return;

          unsigned int magicNumber = 0;
          bool reply = false;

          memcpy(&amp;magicNumber, data+sizeof(mID) /* skip ID */, sizeof(magicNumber));
          memcpy(&amp;reply, data+sizeof(mID)+sizeof(magicNumber) /*skip ID &amp; magicNumber*/, sizeof(reply));

          Init(magicNumber, reply);
      }

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      int mID;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS
      void Init(unsigned int magicNumber, bool reply)
      {
          mData.magicNumber = magicNumber;
          mData.reply = reply;
          mpData = new char[sizeof(mID) + sizeof(S_PingData)];
          memcpy(mpData, &amp;mID, sizeof(mID));
          memcpy(mpData + sizeof(mID), &amp;mData, sizeof(mData));
      }

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      S_PingData mData;
  };

} // netCodeCommon
</code></pre>
<p>Wie ihr sehen könnt allokiere ich beim Anlegen eines Objekts einen char array in der Größe meiner Datenstruktur und kopiere dann nacheinander alles per memcpy in den Array. Durch das händische Kopieren der einzelnen struct members umgehe ich evtl memory alignments, denn meine Daten müssen linear im Speicher liegen, dass SDL mein Paket korrekt verschicken kann.</p>
<p>So, prinzipiell funktioniert das auch, aber mir gefällt diese Art der Implementierung aus zweierlei Gründen nicht:</p>
<ol>
<li>Bei größeren Paketen wird das Kopieren der Daten aufgrund der einzelnen memcpys schnell unübersichtlich und fehleranfällig.</li>
<li>Aus Performancesicht ist diese Lösung sicherlich auch suboptimal. Ausserdem kommts mir irgendwie stümperhaft vor <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></li>
</ol>
<p>Es muss doch irgendetwas schickes geben, womit ich arbiträre Daten linear in den Speicher kriege und über einen char* ansprechen, und die Daten auch von einem char* wieder rekonstruieren kann (wenn das Paket am Zielrechner ankommt).</p>
<p>STL, Boost o.ä. bin ich selbstverständlich nicht abgeneigt.</p>
<p>Hat jemand vielleicht eine Idee?</p>
<p>Danke schonmal <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Edit:<br />
Oder was evtl sogar sinnvoller wäre: Gibts es irgendwelche Bibliotheken mit denen man Klassen per TCP/IP, bzw. UDP serialisieren kann?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/241539/suche-implentierungsideen</link><generator>RSS for Node</generator><lastBuildDate>Mon, 21 Sep 2026 10:00:58 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/241539.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 22 May 2009 05:55:50 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 11:32:57 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich kämpfe momentan mit einem - da bin ich mir eigentlich sicher- relativ banalem Problem. Irgendwie stehe ich aber auf dem Schlauch und bekomme nichts vernünftiges hin.<br />
Vielleicht hat ja von euch jemand eine zündende Idee <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Es geht um folgendes:<br />
Ich brauche eine Klasse, die UDP Datenpakete wrapped.<br />
Momentan habe ich das folgendermaßen aufgezogen:<br />
Meine Basisklasse enthält im Grunde nichts weiter als einen char*, den ich brauche um meine Daten später an SDLNet_UDP_Send weitergeben kann (benötigt seine Daten als char*)</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES

/// LOCAL INCLUDES

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
  class CUDPPacketData
  {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
        CUDPPacketData( ) 
            : mpData(0)
        {}

      /// Destructor
        virtual ~CUDPPacketData() {}

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      const char* BaseData() const { return mpData; }

      ///////////// MEMBERS
      char* mpData;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
  };

} // netCodeCommon
</code></pre>
<p>Davon leite ich mir meine UDP Paket Basisklasse ab, die als pure virtual Klasse die Interfaces zur Verfügung steht, die letztendlich von den Implentierungsklassen implementiert werden:</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES

/// LOCAL INCLUDES
#include &quot;UDPPacketData.hpp&quot;

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
  //template &lt;typename T = void&gt;
  class CUDPPacket : public CUDPPacketData
  {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
      CUDPPacket( )
      {
      }

      /// Destructor
      virtual ~CUDPPacket() { PacketReceived(); }

      ///////////// METHODS
      void PacketReceived()
      {
          if ( 0 != mpData )
              delete [] mpData;
      }

      ///////////// OPERATORS

      ///////////// ACCESSORS
      const char* PacketData() { return mpData; }
     // virtual const T* Data() const = 0;
      virtual const size_t DataLen() const = 0;
      virtual const size_t TotalLen() const = 0;
      virtual const int ID() const = 0;
      virtual void RestoreFromData(char* data) = 0;

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      int mID;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
  };

} // netCodeCommon
</code></pre>
<p>So, jetzt geht es ans Eingemachte.<br />
Ich habe für jede Aufgabe ein eigenes UDP Paket, ergo auch eine eigene Klasse.<br />
Nehmen wir mal exemplarisch meine Ping Klasse:</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES

/// PROJECT INCLUDES
#include &lt;netCode/common/UDPPacket.tpp&gt;
#include &lt;netCode/common/exception.hpp&gt;

/// LOCAL INCLUDES
#include &quot;UDPPacketIDs.h&quot;

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
    struct S_PingData
    {
        unsigned int magicNumber;
        bool reply;
    };

    class CUDPPing : public CUDPPacket // &lt;S_PingData&gt;, CAllocatableObject
    {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
      CUDPPing(char* data)
          : mID(Type_Ping) 
      {
          RestoreFromData(data);
      }

      CUDPPing(unsigned int magicNumber, bool reply)
          : mID(Type_Ping)
      {
          Init(magicNumber, reply);
      }

      /// Destructor
      virtual ~CUDPPing() { if ( 0 != mpData ) delete [] mpData; }

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      virtual const S_PingData* Data() const
      {
          return reinterpret_cast&lt;S_PingData*&gt;(mpData + sizeof(mID));
      }

      virtual const size_t DataLen() const { return sizeof(S_PingData); }
      virtual const size_t TotalLen() const { return sizeof(S_PingData) + sizeof(mID); }
      virtual const int ID() const { return mID; }
      virtual void RestoreFromData(char* data)
      {
          if ( 0 == data) return;

          unsigned int magicNumber = 0;
          bool reply = false;

          memcpy(&amp;magicNumber, data+sizeof(mID) /* skip ID */, sizeof(magicNumber));
          memcpy(&amp;reply, data+sizeof(mID)+sizeof(magicNumber) /*skip ID &amp; magicNumber*/, sizeof(reply));

          Init(magicNumber, reply);
      }

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      int mID;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS
      void Init(unsigned int magicNumber, bool reply)
      {
          mData.magicNumber = magicNumber;
          mData.reply = reply;
          mpData = new char[sizeof(mID) + sizeof(S_PingData)];
          memcpy(mpData, &amp;mID, sizeof(mID));
          memcpy(mpData + sizeof(mID), &amp;mData, sizeof(mData));
      }

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      S_PingData mData;
  };

} // netCodeCommon
</code></pre>
<p>Wie ihr sehen könnt allokiere ich beim Anlegen eines Objekts einen char array in der Größe meiner Datenstruktur und kopiere dann nacheinander alles per memcpy in den Array. Durch das händische Kopieren der einzelnen struct members umgehe ich evtl memory alignments, denn meine Daten müssen linear im Speicher liegen, dass SDL mein Paket korrekt verschicken kann.</p>
<p>So, prinzipiell funktioniert das auch, aber mir gefällt diese Art der Implementierung aus zweierlei Gründen nicht:</p>
<ol>
<li>Bei größeren Paketen wird das Kopieren der Daten aufgrund der einzelnen memcpys schnell unübersichtlich und fehleranfällig.</li>
<li>Aus Performancesicht ist diese Lösung sicherlich auch suboptimal. Ausserdem kommts mir irgendwie stümperhaft vor <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></li>
</ol>
<p>Es muss doch irgendetwas schickes geben, womit ich arbiträre Daten linear in den Speicher kriege und über einen char* ansprechen, und die Daten auch von einem char* wieder rekonstruieren kann (wenn das Paket am Zielrechner ankommt).</p>
<p>STL, Boost o.ä. bin ich selbstverständlich nicht abgeneigt.</p>
<p>Hat jemand vielleicht eine Idee?</p>
<p>Danke schonmal <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Edit:<br />
Oder was evtl sogar sinnvoller wäre: Gibts es irgendwelche Bibliotheken mit denen man Klassen per TCP/IP, bzw. UDP serialisieren kann?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1713999</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1713999</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 11:32:57 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 11:56:55 GMT]]></title><description><![CDATA[<p>was hast du gegen string?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714137</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714137</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 22 May 2009 11:56:55 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 12:29:25 GMT]]></title><description><![CDATA[<p>An und für sich nichts, allerdings bläst sich dann mein Speicherverbrauch ziemlich auf.<br />
Bei diesem Ping Paket würde es sicherlich gehen, aber ich habe auch Pakete, die floating point 4x4 Matrizen beinhalten, von welchen pro Sekunde etwa 180-200 Stück verschickt werden müssen.<br />
Das wären bei einer Stringrepräsentation ~22kb/s - eine Menge Holz finde ich.</p>
<p>Ausserdem müsste ich dann ziemlich viel hin und her casten.</p>
<p>Aber danke für den Ansatz - ich denke auf jeden Fall noch mal genauer drüber nach.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714153</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714153</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 12:29:25 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 12:29:41 GMT]]></title><description><![CDATA[<p>Die Bevölkerung ist geschockt. Volkard schläg einen String als Lösungsvorschlag für die Serialisierung vor. Nach ansicht führender Serialisierungsexperten eine komplette Fehleinschätzung des Themas mit weitreichenden Konsequenzen. Ich schalte jetzt live nach Komutischtun, wo die Lage zu eskalieren droht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714154</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714154</guid><dc:creator><![CDATA[Nachrichtensprecher]]></dc:creator><pubDate>Fri, 22 May 2009 12:29:41 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 12:47:14 GMT]]></title><description><![CDATA[<p>Ich beschäftige mich jetzt mal etwas genauer mit Serialisierung im Allgemeinen.<br />
Ich denke <a href="http://www.parashift.com/c++-faq-lite/serialization.html#faq-36.9" rel="nofollow">hier</a> oder <a href="http://www.heise.de/ix/artikel/2008/02/138/" rel="nofollow">hier</a> werde ich schon irgendwie weiterkommen.</p>
<p>Aber sagt ruhig bescheid, wenn euch was gutes einfällt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714172</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714172</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 12:47:14 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 12:52:25 GMT]]></title><description><![CDATA[<p>nein, nein. ich meine doch nur string und keine serialisierung.<br />
string ist eine sequenz von chars. sie kann auch nullen enthalten. und man kann effizient hintendranhängen. string einfach nur als datenspeicher klasse, die dir das new/delete und wachsenlassen abnimmt.</p>
<pre><code class="language-cpp">outputString.append(reinterpret_cast&lt;char const*&gt;(&amp;magicNumber),sizeof(magicNumber));
</code></pre>
<p>und wenn das paket dann weg soll</p>
<pre><code class="language-cpp">send(socket,outputString.begin(),outputString.size());
</code></pre>
<p>oder so.</p>
<p>kann mir nicht vorstellen, daß dabei irgendwas merklich teurer wird, als wenn man den speicher selber anfaßt und memcpy macht.</p>
<p>in der nähe tollen sich noch vector&lt;char&gt; mit push_back() und ostringstream mit ganz normalem write.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714181</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714181</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 22 May 2009 12:52:25 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 12:58:27 GMT]]></title><description><![CDATA[<p>Warum nicht std::vector&lt;char&gt; ? Wirkt für mich natürlicher als std::string.</p>
<p>Simon</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714190</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714190</guid><dc:creator><![CDATA[theta]]></dc:creator><pubDate>Fri, 22 May 2009 12:58:27 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:01:39 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/106">@volkard</a>: Ah, jetzt hab ichs kapiert <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Das geht dann ja auch in die Richtung was die Serialisierungs Sektion bei Parashift erklärt - nur halt eben mit nem String.<br />
Gefällt mir...werd mal bischen rumspielen und schauen, was sich am besten für mich eignet - String, vector oder stream</p>
<p>Danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714192</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714192</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 13:01:39 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:05:50 GMT]]></title><description><![CDATA[<p>theta schrieb:</p>
<blockquote>
<p>Warum nicht std::vector&lt;char&gt; ?</p>
</blockquote>
<p>Weil es zum Teil wahnsinnig mühsam ist, in einen <code>std::vector&lt;char&gt;</code> zu schreiben. Probier mal das aus, was volkard im Beispielcode gezeigt hat:</p>
<pre><code class="language-cpp">char const* first = reinterpret_cast&lt;char const*&gt;(&amp;magicNumber);
char const* last = first + sizeof(magicNumber);
outputVector.insert(outputVector.end(), first, last);
</code></pre>
<p>-&gt; Gah!</p>
<p>Grüssli <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714201</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714201</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Fri, 22 May 2009 13:05:50 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:09:08 GMT]]></title><description><![CDATA[<p>theta schrieb:</p>
<blockquote>
<p>Warum nicht std::vector&lt;char&gt; ?</p>
</blockquote>
<p>weil ich's am häufigsten mit string gesehen habe, fiel mir das spontan ein. aber im moment glaube ich, daß ostringstream naheliegender als string ist. wie gut, daß ich das problem nicht habe und Hydrael es rausfinden muß. hehe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714206</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714206</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 22 May 2009 13:09:08 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:12:33 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>theta schrieb:</p>
<blockquote>
<p>Warum nicht std::vector&lt;char&gt; ?</p>
</blockquote>
<p>weil ich's am häufigsten mit string gesehen habe, fiel mir das spontan ein. aber im moment glaube ich, daß ostringstream naheliegender als string ist. wie gut, daß ich das problem nicht habe und Hydrael es rausfinden muß. hehe.</p>
</blockquote>
<p>Werde heute Nacht irgendwann bescheidgeben wie es geklappt hat - aber ausm Bauch heraus denke ich, dass es mit nem ostringstream ziemlich gut klappen müsste <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714213</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714213</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 13:12:33 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:16:11 GMT]]></title><description><![CDATA[<p>ja, da hat Dravere recht.<br />
aber ein wenig später schreibt man sich eh wrappers.</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
writeAny(outputVector&lt;char&gt;&amp; v,T&amp; magicNumber){
  char const* first = reinterpret_cast&lt;char const*&gt;(&amp;magicNumber);
  char const* last = first + sizeof(magicNumber);
  outputVector.insert(outputVector.end(), first, last);
}
</code></pre>
<p>und später</p>
<pre><code class="language-cpp">writeAny(outputVector,magicNumber);
</code></pre>
<p>dann ists wieder egal.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714216</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714216</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 22 May 2009 13:16:11 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:27:09 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/106">@volkard</a>,<br />
Auch wieder wahr.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/13111">@Hydrael</a>,<br />
Bin gespannt auf deine Testergebnisse mit dem <code>stringstream</code> . Ich persönlich hatte mal einen Fall, wo ich <code>std::string</code> Objekte zusammen setzen musste. Seither weiss ich, dass das einfache zusammenfügen von <code>std::string</code> Objekte oft schneller ist, wenn man kein <code>stringstream</code> verwendet, sondern direkt über die <code>std::string</code> Möglichkeiten geht.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714225</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714225</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Fri, 22 May 2009 13:27:09 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 13:32:28 GMT]]></title><description><![CDATA[<p>Warum gebt ihr nicht gleich den reinterpret_cast&lt;char const*&gt;(&amp;magicNumber) an den Socket?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714232</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714232</guid><dc:creator><![CDATA[Themen-Überblick  (Aktual]]></dc:creator><pubDate>Fri, 22 May 2009 13:32:28 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 16:16:00 GMT]]></title><description><![CDATA[<p>Themen-Überblick  (Aktual schrieb:</p>
<blockquote>
<p>Warum gebt ihr nicht gleich den reinterpret_cast&lt;char const*&gt;(&amp;magicNumber) an den Socket?</p>
</blockquote>
<p>Weil es ja im Grunde nicht nur um die magicNumber geht, sondern um komplette datenstrukturen. Kann also durchaus auch sowas sein:</p>
<pre><code class="language-cpp">struct foo
{
  char bar;
  int foo1;
  short bar1;
}
</code></pre>
<p>Und da kann man ganz schnell in memory alignment Geschichten reinlaufen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714322</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714322</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 16:16:00 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 16:57:37 GMT]]></title><description><![CDATA[<p>Die hast du bei memcpy und volkards Methode auch, da macht ihr ja auch nur nen reinterpret cast.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714337</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714337</guid><dc:creator><![CDATA[Themen-Überblick (Aktual]]></dc:creator><pubDate>Fri, 22 May 2009 16:57:37 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 19:11:27 GMT]]></title><description><![CDATA[<p>So, ich habe jetzt mal ein wenig herumprobiert - letzendlich bin ich beim std::strstream hängengeblieben, weil ich beim stringstream das Problem hatte, dass er die Daten als strings reinterpretiert und ich somit bei den Binärdaten bullshit herausbekommen habe.</p>
<p>Mit dem strstream funktioniert die Sache tadellos und ist auch schön einfach implementierbar <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Einen herzlichen Dank an alle Helfer - die Lösung gefällt mir jetzt echt gut.<br />
Einzig zur Performance kann ich momentan noch nichts genaues sagen, da ich die im derzeitigen Projektstand noch nicht realistisch messen kann.</p>
<p>Wen es interessiert...meine Klassen sehen jetzt folgendermaßen aus (diesmal am Beispiel eines anderen Pakets, so dass zu sehen ist, wie ich mit strings umgehe):</p>
<p>Basisklasse</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES
#include &lt;strstream&gt;

/// PROJECT INCLUDES

/// LOCAL INCLUDES

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
  class CUDPPacket
  {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor
      CUDPPacket( )
      {
      }

      /// Destructor
      virtual ~CUDPPacket() {  }

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      virtual const size_t DataLen() const = 0;
      virtual const size_t TotalLen() const = 0;
      const int ID() const { return mID; }
      virtual const std::strstream&amp; Serialize() = 0;
      virtual void Deserialize(const std::strstream&amp; data) = 0;

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      int mID;
      std::strstream mSerializationStream;

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
  };

} // netCodeCommon
</code></pre>
<p>Abgeleitete Klasse</p>
<pre><code class="language-cpp">#pragma once

/// SYSTEM INCLUDES
#include &lt;string&gt;

/// PROJECT INCLUDES
#include &lt;netCode/common/UDPPacket.tpp&gt;
#include &lt;netCode/common/exception.hpp&gt;

/// LOCAL INCLUDES
#include &quot;UDPPacketIDs.h&quot;

/// FORWARD DECLARATIONS

namespace netCodeCommon
{
    struct S_RegisterPlayerData
    {
        S_RegisterPlayerData()
            : magicNumber(0),
              playerName(&quot;&quot;)
        {
        }
        S_RegisterPlayerData(unsigned int magic, const std::string&amp; name)
            : magicNumber(magic),
              playerName(name)
        {
        }
        unsigned int magicNumber;
        std::string playerName;

        const size_t size() const { return sizeof(magicNumber) + playerName.length(); }
    };

    class CUDPRegisterPlayer : public CUDPPacket
    {
    //////////////////////// PUBLIC //////////////////////////
    public:
      /// Constructor

      CUDPRegisterPlayer(char* data, size_t len)
      {
          mID = Type_RegisterPlayer;
          mSerializationStream.write(data, len);
          Deserialize(mSerializationStream);
      }

      CUDPRegisterPlayer(unsigned int magicNumber, const std::string&amp; playerName)
      {
          mID = Type_RegisterPlayer;
          mData.playerName = playerName;
          mData.magicNumber = magicNumber;
      }

      /// Destructor
      virtual ~CUDPRegisterPlayer() { }

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS
      virtual const S_RegisterPlayerData&amp; Data() const 
      {
          return mData;
      }

      virtual const size_t DataLen() const { return mData.size() + sizeof(mID); }
      virtual const size_t TotalLen() const { return mData.size() + sizeof(mID) + sizeof(size_t); }
      virtual const std::strstream&amp; Serialize()
      {
          size_t length = mData.playerName.length();
          mSerializationStream.clear();
          mSerializationStream.write(reinterpret_cast&lt;char*&gt;(&amp;mID), sizeof(mID));
          mSerializationStream.write(reinterpret_cast&lt;char*&gt;(&amp;mData.magicNumber), sizeof(mData.magicNumber));
          mSerializationStream.write(reinterpret_cast&lt;char*&gt;(&amp;length), sizeof(length));
          mSerializationStream.write(mData.playerName.c_str(), mData.playerName.length());
          mSerializationStream.seekg(0, std::ios::beg);
          return mSerializationStream;
      }
      virtual void Deserialize(const std::strstream&amp; data)
      {
          size_t length = 0;
          mSerializationStream.read(reinterpret_cast&lt;char*&gt;(&amp;mID), sizeof(mID));
          mSerializationStream.read(reinterpret_cast&lt;char*&gt;(&amp;mData.magicNumber), sizeof(mData.magicNumber));
          mSerializationStream.read(reinterpret_cast&lt;char*&gt;(&amp;length), sizeof(length));
          char *tmp = new char[length + 1];
          mSerializationStream.read(tmp, length);
          tmp[length] = '\0';
          mData.playerName = tmp;
          mSerializationStream.clear();
      }

      ///////////// MEMBERS

      /////////////////////// PROTECTED ///////////////////////
    protected:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS

      /////////////////////// PRIVATE //////////////////////////
    private:

      ///////////// METHODS

      ///////////// OPERATORS

      ///////////// ACCESSORS

      ///////////// MEMBERS
      S_RegisterPlayerData mData;
  };

} // netCodeCommon
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1714381</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714381</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 19:11:27 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 19:45:24 GMT]]></title><description><![CDATA[<p>Hydrael schrieb:</p>
<blockquote>
<p>letzendlich bin ich beim std::strstream hängengeblieben, ...</p>
</blockquote>
<p><code>std::strstream</code> ist <em>deprecated</em> und es ist wahrscheinlich, dass in zukünftigen Versionen des Standards diese Klasse nicht mehr existieren wird.</p>
<p>Hydrael schrieb:</p>
<blockquote>
<p>weil ich beim stringstream das Problem hatte, dass er die Daten als strings reinterpretiert und ich somit bei den Binärdaten bullshit herausbekommen habe.</p>
</blockquote>
<p>Wie hast du denn in den <code>std::stringstream</code> geschrieben? Aber nicht mit dem <code>operator &lt;&lt;</code> ? Es gibt nämlich eine <code>write</code> Methode, welche du nutzen solltest:<br />
<a href="http://www.cplusplus.com/reference/iostream/ostream/write/" rel="nofollow">http://www.cplusplus.com/reference/iostream/ostream/write/</a></p>
<p>Den <code>std::stringstream</code> zudem mit dem Flag <code>std::ios::binary</code> erstellen, damit die Daten beim Schreiben nicht verändert werden.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714395</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714395</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Fri, 22 May 2009 19:45:24 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 19:50:53 GMT]]></title><description><![CDATA[<p>sieht gut aus.</p>
<p>aber warum nicht</p>
<pre><code class="language-cpp">virtual void Serialize(std::strstream&amp; data) = 0; 
      virtual void Deserialize(std::strstream&amp; data) = 0;
</code></pre>
<p>damits gleicher aussieht. der returnwert war eh fake. und const auf einem stream gleube ich dir nicht.</p>
<p>uups, nee, dann schon gleich</p>
<pre><code class="language-cpp">virtual void Serialize(std::ostrstream&amp; data) = 0; 
      virtual void Deserialize(std::istrstream&amp; data) = 0;
</code></pre>
<p>uups, dann gleich</p>
<pre><code class="language-cpp">virtual void Serialize(std::ostream&amp; data) = 0; 
      virtual void Deserialize(std::istream&amp; data) = 0;
</code></pre>
<p>dann kannst du mit derselben funktion auch in dateien speichern und daraus laden.</p>
<p>oder gar im netz nach einer sockestream-implementierungen suchen, falls es sowas gibt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714398</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714398</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 22 May 2009 19:50:53 GMT</pubDate></item><item><title><![CDATA[Reply to Suche Implentierungsideen on Fri, 22 May 2009 20:10:50 GMT]]></title><description><![CDATA[<p>Dravere schrieb:</p>
<blockquote>
<p><code>std::ios::binary</code></p>
</blockquote>
<p>Das war es, was mir gefehlt hatte <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/106">@volkard</a>: Der const stream war noch ein copy/paste überbleibsel - ist mir kurz nach dem posten auch aufgefallen.<br />
Ansonsten hab ich deine Anmerkungen auch noch übernommen.<br />
Wie man sieht bin ich nicht so sehr fit mit streams. Hatte die bisher immer nur für file I/O benötigt und da war mir oldschool fread/fwrite irgendwie immer lieber <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Schönen Dank euch beiden</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1714405</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1714405</guid><dc:creator><![CDATA[Hydrael]]></dc:creator><pubDate>Fri, 22 May 2009 20:10:50 GMT</pubDate></item></channel></rss>