Javier Urrestarazu
Javier Urrestarazu

Reputation: 83

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.

Upvotes: 1

Views: 1818

Answers (2)

Victor Gubin
Victor Gubin

Reputation: 2937

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;

Upvotes: 1

Acorn
Acorn

Reputation: 26136

That is not going to work. You can only send raw data through a connection since ASIO does not perform any serialization. std::string is not a trivial type and also contains members (like pointers) that do not make sense to send over a connection. Further, a structure may not be portable between computers of different kinds.

You will have to use something like the Boost Serialization library, Protobuffers or a similar library; or perform similar duties yourself.

Upvotes: 0

Related Questions