Подтвердить что ты не робот

Сериализовать и отправить структуру данных с помощью Boost?

У меня есть структура данных, которая выглядит так:

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

Я хочу использовать boost:: serialization для сериализации этой структуры данных, а затем использовать boost:: asio для передачи через TCP/IP, а затем другое приложение получает данные и де-сериализует их с использованием тех же самых библиотек boost.

Я пытаюсь выполнить boost:: serialization учебник, ( как некоторые другие вопросы SO предложили), но пример специально предназначен для записи/чтения в файл, а не для сокета с использованием boost:: asio.

Я уверен, что у меня есть подходящие инструменты для работы - мне просто нужна помощь, чтобы они работали вместе. Запись в сокет не может отличаться от записи в файл, не так ли?

Любые предложения очень ценятся. Спасибо!

4b9b3361

Ответ 1

Для такой простой структуры boost:: serialization - это избыток и огромные накладные расходы.

Сделайте проще:

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

И сохраните ОГРОМНЫЕ служебные данные, которые ускоряют: сериализация

И если вы являетесь частным протоколом, где работают компьютеры с одинаковым порядком байтов (большие/маленькие) что просто отправить структуру как есть - POD.

Ответ 2

В документации asio есть хороший пример сериализации: server.cpp, stock.hpp, connection.hpp.

Вот фрагмент:

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

Ответ 3

Я думал, что поделился бы этим с любым, кто пытался сериализовать С++ struct с помощью Boost. В приведенном выше примере, чтобы сделать сериализуемое struct, вы добавили бы функцию 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;

Ответ 4

EDIT: я верну свой ответ ниже, то, что я предлагаю, имеет преимущества времени и пространства над решением строкового потока, но API-интерфейс asio:: stream не обладает некоторыми важными функциями, которые понадобятся в долгосрочной перспективе (например, временное прерывание).


Мой оригинальный ответ:

Используйте потоки из boost:: asio, у него есть преимущества времени и пространства, прежде чем записывать его в std:: stringstreams, а затем отправлять его за один раз. Вот как:

Клиентский код:

boost::asio::ip::tcp::iostream stream("localhost", "3000");

if (!stream)
  throw std::runtime_error("can't connect");

Код сервера:

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

И затем, после того, как вы подключаетесь либо к клиентскому, либо к серверному потоку, просто выполните:

MyDataType obj;

// Send the object.
boost::archive::text_oarchive archive(stream);
archive << obj;

// Or receive it.
boost::archive::text_iarchive archive(stream);
archive >> obj;

Вам, конечно, нужно добавить функцию "сериализовать" в свой MyDataType, как писал Таймек в своем ответе.

Ответ 5

Вы выполняете сериализацию для boost:: archive, которые получают параметр конструктора - целевой поток, в котором вы будете сохранять данные. Вы можете использовать библиотеку boost.iostreams для определения собственного потока, который будет отправлять данные по сети, а не файлы или просто использовать потоки сокетов asio (http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/ip__tcp/iostream.html). Это хороший способ, мы сделали что-то подобное на этом, но у нас мало потоков (zip/encrypt/send) и использовалась библиотека boost iostreams для всех операций.

Простой и фиктивный способ - хранить ваши данные во временном файле и отправлять этот файл:)

Ответ 6

Архивация сериализации boost может быть построена с любым потоком. Таким образом, любой анархист может использовать любой ostream, и любой iarchive может использовать любой istream. Таким образом, вы можете архивировать в ostringstream, передавать строку с asio и восстанавливать данные из этого.

См. ссылку binary_oarchive здесь, например.

Ответ 7

Я подозреваю, что вы захотите сначала архивировать в память, а затем записать это в сокет.