Как сериализовать объект для отправки по сети - PullRequest
8 голосов
/ 16 июля 2010

Я пытаюсь сериализовать объекты для отправки по сети через сокет, используя только STL. Я не нахожу способ десериализации структуры объектов на другом хосте. Я попытался преобразовать в string, в char*, и я потратил много времени на поиск учебников в Интернете, и до сих пор я ничего не нашел.

Есть ли способ сделать это только с STL?

Есть ли хорошие уроки?

Я почти пытаюсь повысить, но если есть способ сделать это с STL, я бы хотел узнать.

Ответы [ 5 ]

7 голосов
/ 16 июля 2010

Вы можете сериализовать что угодно. Все средства сериализации заключаются в том, что вы конвертируете объект в байты, чтобы вы могли отправить его по потоку (например, std::ostream) и прочитать его с другим (например, std::istream). Просто переопределите operator <<(std::ostream&, const T&) и operator >>(std::istream&, T&), где T - это каждый из ваших типов. И все типы, содержащиеся в ваших типах.

Однако вам, вероятно, следует просто использовать уже существующую библиотеку (Boost довольно хорош). Есть множество вещей, которые библиотека для вас делает для вас, такие как упорядочение байтов, забота об общих объектах (таких как массивы и все остальное из стандартной библиотеки), предоставляя согласованные средства выполнения сериализации и множество других вещей.

5 голосов
/ 16 июля 2010

Мой первый вопрос будет: хотите ли вы сериализацию или обмен сообщениями?

Сначала это может показаться глупым, поскольку вы просили сериализацию, но потом я всегда различал два термина.

  • Сериализация - это создание снимка вашей памяти и его восстановление позже.Каждый объект представлен как отдельный объект (хотя они могут быть составлены)
  • Обмен сообщениями - это отправка информации из одной точки в другую.Сообщение обычно имеет собственную грамматику и может не отражать организацию вашей бизнес-модели.

Слишком часто я видел людей, использующих сериализацию, где должен был использоваться обмен сообщениями.Это не означает, что сериализация бесполезна, но это означает, что вы должны думать заранее.Довольно сложно изменить спецификацию после того, как вы решили ее сериализовать, особенно если вы решили переместить некоторую часть информации (переместить ее из одного объекта в другой) ... потому что как вы собираетесь декодировать "старый" сериализованныйверсия?

Теперь, когда все прояснено ...

... Я порекомендую буфер протокола Google.

Вы можете прекрасно переписать свой собственный, используя STL, нов конечном итоге вы будете выполнять работу, которая уже сделана, и если вы не хотите учиться на ней, это совершенно бессмысленно.

Одна замечательная вещь в protobuf заключается в том, что она не зависит от языка в некотором смысле: то есть вы можетегенерировать кодер / декодер данного сообщения для C ++, Java или Python.Использование Python удобно для внедрения сообщений (тестирования) или декодирования сообщений (для проверки вывода зарегистрированного сообщения).Это было бы не просто, если бы вы использовали STL.

1 голос
/ 14 ноября 2016

Сериализация объектов C ++ по сетевому сокету

Это на 6 лет позже, но я только недавно столкнулся с этой проблемой, и это был один из потоков, с которыми я столкнулся при поиске, как сериализовать объект через сетевой сокет в C ++. Это решение использует всего 2 или 3 строки кода. Я нашел много ответов, но мне было проще всего использовать reinterpret_cast<obj*>(target) для преобразования класса или структуры в массив символов и передачи их через сокет. Вот пример.

Класс для сериализации:

/* myclass.h */

#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass
{
    public:
        int A;
        int B;
        MyClass(){A=1;B=2;}
        ~MyClass(){}
};

#endif

Серверная программа:

/* server.cpp */

#include "myclass.h"

int main (int argc, char** argv)
{
    // Open socket connection.
    // ...

    // Loop continuously until terminated.
    while(1)
    {
        // Read serialized data from socket.
        char buf[sizeof(MyClass)];
        read(newsockfd,buf, sizeof(MyClass));
        MyClass *msg = reinterpret_cast<MyClass*>(buf);  

        std::cout << "A = " << std::to_string(msg->A) << std::endl;
        std::cout << "B = " << std::to_string(msg->B) << std::endl;
    }

    // Close socket connection.
    // ...

    return 0;
}

Клиентская программа:

/* client.cpp */

#include "myClass.h"

int main(int argc, char *argv[])
{
    // Open socket connection.
    // ...

    while(1)
    {
        printf("Please enter the message: ");
        bzero(buffer,256);
        fgets(buffer,255,stdin);

        MyClass msg;
        msg.A = 1;
        msg.B = 2;

        // Write serialized data to socket.
        char* tmp = reinterpret_cast<char*>(&msg);
        write(sockfd,tmp, sizeof(MyClass));
    }

    // Close socket connection.
    // ...

    return 0;
}

Скомпилируйте server.cpp и client.cpp , используя g++ с -std=c++11 в качестве опции. Затем вы можете открыть два терминала и запустить обе программы, однако запустите серверную программу перед клиентом, чтобы ему было к чему подключаться.

Надеюсь, это поможет.

0 голосов
/ 25 января 2015

Я думаю, вы должны использовать google Protocol Buffers в своем проекте. В сетевом транспортном протоколе буферы протокола имеют много преимуществ перед XML для сериализации структурированных данных.Буферы протокола:

проще в 3-10 раз меньше, в 20-100 раз быстрее, менее неоднозначно генерирует классы доступа к данным, которые проще использовать программно

и так далее.Я думаю, вам нужно прочитать https://developers.google.com/protocol-buffers/docs/overview о protobuf

0 голосов
/ 23 июля 2010

Я понял!

Я использовал strinstream для сериализации объектов и отправил его как сообщение с использованием метода stringstream str () и, следовательно, c_str () строки.

Посмотрите.

class Object {
public:
int a;
string b;

void methodSample1 ();
void methosSample2 ();

friend ostream& operator<< (ostream& out, Object& object) {
out << object.a << " " << object.b;   //The space (" ") is necessari for separete elements
return out;
}

friend istream& operator>> (istream& in, Object& object) {
in >> object.a;
in >> object.b;
return in;
}
};

/* Server side */
int main () {
Object o;
stringstream ss;
o.a = 1;
o.b = 2;
ss << o;    //serialize

write (socket, ss.str().c_str(), 20); //send - the buffer size must be adjusted, it's a sample
}

/* Client side */
int main () {
Object o2;
stringstream ss2;
char buffer[20];
string temp;

read (socket, buffer, 20);  //receive
temp.assign(buffer);
ss << temp;
ss >> o2;   //unserialize
}

Я не уверен, нужно ли преобразовывать в строку перед сериализацией (ss << o), возможно, это возможно непосредственно из char. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...