punteros estructuras estructura ejercicios datos anidadas c++ serialization boost boost-asio

c++ - estructuras - ¿Serializar y enviar una estructura de datos utilizando Boost?



punteros c++ youtube (7)

Tengo una estructura de datos que se parece a esto:

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

Quiero usar boost :: serialización para serializar esta estructura de datos, luego usar boost :: asio para transmitirlo a través de TCP / IP, luego hacer que otra aplicación reciba los datos y des-serializarlos usando las mismas bibliotecas de boost.

Estoy intentando seguir el tutorial boost :: serialización , ( como han sugerido otras preguntas de SO ) pero el ejemplo es específicamente para escribir / leer en un archivo, no en un socket que usa boost :: asio.

Estoy bastante seguro de que tengo las herramientas adecuadas para el trabajo, solo necesito ayuda para que trabajen juntos. Escribir en un socket no puede ser tan diferente de escribir en un archivo, ¿verdad?

Cualquier sugerencia es muy apreciada. ¡Gracias!


EDITAR: Retiro mi respuesta a continuación, lo que propuse tiene las ventajas de tiempo y espacio con respecto a la solución stringstream, pero la API asio :: stream carece de algunas funciones importantes que serán necesarias a largo plazo (por ejemplo, interrupción temporizada).

Mi respuesta original:

Use streams de boost :: asio, tiene ventajas de tiempo y espacio al escribirlo en std :: stringstreams y luego enviarlo de una sola vez. Aquí es cómo:

Codigo del cliente:

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

Código del servidor:

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());

Y luego, una vez que se haya conectado con el cliente o con el servidor, simplemente haga lo siguiente:

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

Por supuesto, debe agregar la función ''serializar'' en su MyDataType como escribió Tymek en su respuesta.


Está haciendo la serialización para aumentar :: archive que obtiene el parámetro constructor - flujo de destino, donde guardará los datos. Puede usar la biblioteca boost.iostreams para definir su propia transmisión que enviará datos a través de la red, en lugar de archivos o simplemente use secuencias de sio asio ( http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/ip__tcp/iostream.html ). Es una buena manera, hicimos algo similar en esto, pero tenemos pocas transmisiones (zip / encrypt / send) y usamos la biblioteca boost iostreams para todas las operaciones.

Manera fácil y ficticia: almacene sus datos en un archivo temporal y envíe este archivo :)


Hay un buen example serialización en la documentación de asio: server.cpp , stock.hpp , connection.hpp .

Aquí hay un fragmento de código:

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);


Los archivos de serialización boost pueden construirse con cualquier flujo. Por lo tanto, cualquier oarchive puede usar cualquier ostream, y cualquier iarchive puede usar cualquier istream. Por lo tanto, puede archivar en un flujo de ostringstream, transmitir la cadena con asio y reconstruir los datos a partir de eso.

Vea la referencia de binary_oarchive here , por ejemplo.


Para una estructura tan simple, boost :: serialización es una sobrecarga y una sobrecarga enorme.

Hacer más simple:

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]);

Y ahórrate una sobrecarga enorme que aumenta: la serialización tiene

Y si tiene un protocolo privado en el que las computadoras con el mismo orden de bytes funcionan (grandes / pequeñas) que simplemente envían la estructura como está: POD.


Pensé que compartiría esto con cualquiera que intentara serializar una struct C ++ usando Boost. Para el ejemplo dado arriba, para hacer que la struct serializable usted agregaría una función de serialize :

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;


Sospecho que primero querrá archivar en la memoria y luego escribirlo en el socket.