Serialize and send a data structure using Boost?

后端 未结 7 1263
半阙折子戏
半阙折子戏 2020-12-02 10:45

I have a data structure that looks like this:

typedef struct
{
  unsigned short m_short1;
  unsigned short m_short2;
  unsigned char m_character;
} MyDataType;


        
相关标签:
7条回答
  • 2020-12-02 11:17

    For such simple structure, boost::serialization is overkill and huge overhead.

    Do simpler:

    vector<uint16_t> net(3,0);
    
    net[0]=htons(data.m_short1);
    net[1]=htons(data.m_short2);
    net[2]=htons(data.character);
    
    asio::async_write(socket,buffer((char*)&net.front(),6),callback);
    
    vector<uint16_t> net(3,0);
    asio::async_read(socket,buffer((char*)&net.front(),6),callback);
    
    callback:
    data.m_short1=ntohs(net[0]);
    data.m_short2=ntohs(net[1]);
    data.character=ntohs(net[2]);
    

    And Save yourself HUGE overhead that boost::serialization has

    And if you private protocol where computers with same order of bytes work (big/little) that just send structure as is -- POD.

    0 讨论(0)
  • 2020-12-02 11:22

    EDIT: I take back my answer below, what I proposed does have the time and space advantages over the stringstream solution but the asio::stream API is lacking some important functionality that will be needed in a long run (e.g. timed interruption).


    My original answer:

    Use streams from boost::asio, it has time and space advantages over writing it into std::stringstreams and then sending it in one go. Here is how:

    Client code:

    boost::asio::ip::tcp::iostream stream("localhost", "3000");
    
    if (!stream)
      throw std::runtime_error("can't connect");
    

    Server code:

    boost::asio::io_service ios;
    boost::asio::ip::tcp::endpoint endpoint
      = boost::asio::ip::tcp::endpoint(ip::tcp::v4(), 3000);
    boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
    boost::asio::ip::tcp::iostream stream;
    
    // Your program stops here until client connects.
    acceptor.accept(*stream.rdbuf()); 
    

    And then, after you are connected with either client or server stream just do:

    MyDataType obj;
    
    // Send the object.
    boost::archive::text_oarchive archive(stream);
    archive << obj;
    
    // Or receive it.
    boost::archive::text_iarchive archive(stream);
    archive >> obj;
    

    You of course need to add the 'serialize' function into your MyDataType as Tymek wrote in his answer.

    0 讨论(0)
  • 2020-12-02 11:24

    I thought I'd share this with anyone who was trying to serialize a C++ struct using Boost. For the example given above, to make the struct serializable you would add a serialize function:

    typedef struct
    {
      unsigned short m_short1;
      unsigned short m_short2;
      unsigned char m_character;
    
      template <typename Archive>
      void serialize(Archive& ar, const unsigned int version)
      {
        ar & m_short1;
        ar & m_short2;
        ar & m_character;
      }
    } MyDataType;
    
    0 讨论(0)
  • 2020-12-02 11:33

    There is a good serialization example in the asio documentation: server.cpp, stock.hpp, connection.hpp.

    Here's a snippet:

    std::ostringstream archive_stream;
    boost::archive::text_oarchive archive(archive_stream);
    archive << your_struct;
    outbound_data_ = archive_stream.str();
    boost::asio::async_write(socket_, 
        boost::asio::buffer(outbound_data_), handler);
    
    0 讨论(0)
  • 2020-12-02 11:39

    You doing serialization to boost::archive which get constructor parameter - destination stream, where you will save data. You could use boost.iostreams library for define your own stream which will send data over network, instead file or just use asio socket streams (http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/ip__tcp/iostream.html). It is a good way, we did something similar on this, but we have few streams (zip/encrypt/send) and used boost iostreams library for all operation.

    Easy and dummy way - store your data in temporary file and send this file :)

    0 讨论(0)
  • 2020-12-02 11:39

    The boost serialization archives can be constructed with any stream. Thus any oarchive can use any ostream, and any iarchive can use any istream. Thus you can archive to an ostringstream, transmit the string with asio, and reconstruct the data from that.

    See the reference of binary_oarchive here, for example.

    0 讨论(0)
提交回复
热议问题