Search code examples
c++boostasio

Sending structure over UDP using boost::asio


I need to send a structure of different data types at once through UDP. I have tried using the boost library, but I am unable to send all the structure elements at once. Here is a snippet of the structure I need to send:

    struct sample {
       char a;
       char16_t b;
       char c;
       std::string d;
       char e;
    };
    sample mystruct;

Creating a string concatenating every element doesn't work for me because I am sending hexadecimal values which should not be converted to string. This is the method I am using for sending the information through the socket:

sock.send_to(boost::asio::buffer(&mystruct, sizeof(mystruct)), remote, 0, error);

This is not working because there is additional data that is being sent. I only want to send the elements of the struct, without separation or any kind of data between them.

Thanks in advance.


Solution

  • Sending and receiving structures over network sockets (no mater what type of the socket you are using synchronous or asynchronous TCP, datagram UDP ) logical similar to file read/write. It means - simply dumping the memory approach is not going to work, especially when you structure contains class/structure fields or pointers. Usually serialization approach used instead, e.g. you can serialize you structure into some binary (ASN1, Google Protocol Buffers etc) or text format (XML,JSON,YAML etc) - send the result by network, receive it and de-serialize back to a structure.

    You can use boost serialization for serialization propose.

    I.e. something like:

    #include <boost/archive/text_oarchive.hpp>
    ....
    struct sample {
      char a;
      char16_t b;
      char c;
      std::string d;
      char e;
    };
    namespace boost {
    namespace serialization {
    
    template<class Archive>
    void serialize(Archive & ar,const sample& value, const unsigned int version)
    {
        ar & value.a;
        ar & value.b;
        ar & value.c;
        ar & value.d;
        ar & value.e;
    }
    
    } // namespace serialization
    } // namespace boost
    ...
    sample mystruct;
    ....
    std::ostringstream archive_stream;
    boost::archive::text_oarchive archive(archive_stream);
    archive << mystruct;
    ...
    sock.send_to( boost::asio::buffer(archive_stream.str()), remote, 0, error);
    

    Then you can de-serialize the structure, when received

    #include <boost/archive/text_iarchive.hpp>
    ....
    std::string str;
    str.resize(1024);
    boost::asio::udp::endpoint sender_endpoint;
    std::size_t len = socket.receive_from(
            boost::asio::buffer(str), sender_endpoint);
    ....
    std::istringstream archive_stream(str);
    sample mystruct;
    boost::archive::text_iarchive archive(archive_stream);
    archive >> mystruct;