C++ 结构体的序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16543519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:27:32  来源:igfitidea点击:

Serialization of struct

c++serializationdeserializationwinsock2

提问by Vigo

Suppose i have a struct whose member values i want to send over the network to another system using winsock 2. I'm using C++ language. How do i convert it to char * keeping in mind that the struct has to be serialized before sending and also how do i deserialize the char * into struct at the other end? I found boost serialization as a suggestion to similar question but can anyone illustrate with a small code snippet for both serialization and deserialization ?

假设我有一个结构,我想使用 winsock 2 通过网络将其成员值发送到另一个系统。我使用的是 C++ 语言。我如何将它转换为 char * 记住结构必须在发送之前序列化,以及如何将 char * 反序列化为另一端的结构?我发现 boost 序列化是对类似问题的建议,但谁能用一个小代码片段来说明序列化和反序列化?

This question might seem very basic but the other answers to the related posts did not help much.

这个问题可能看起来很基本,但相关帖子的其他答案并没有多大帮助。

回答by Amith Chinthaka

Following example shows a simplest way to serialize structinto chararray and de-serialize it.

以下示例显示了序列化最简单的方式struct进入char阵列和反序列化。

#include <iostream>
#include <cstring>

#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)

using namespace std;

typedef struct MSG
{
    int type;
    int priority;
    int sender;
    char message[BUFSIZE];
}MSG;

void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);

int main()
{
    MSG* newMsg = new MSG;
    newMsg->type = 1;
    newMsg->priority = 9;
    newMsg->sender = 2;
    strcpy(newMsg->message, "hello from server
struct MyStruct {

    int data;
    char* someNullTerminatedName; // Assuming not larger than 1023 chars

    std::ostream& serialize(std::ostream& os) const {
        char null = '
MyStruct foo, bar;
std::stringstream stream;
foo.serialize(stream);
// ... Now stream.str().c_str() contains a char* buffer representation of foo.
// For example it might contain [ 1f 3a 4d 10 h e l l o w o r l d 
int main() {
    // create and open a character archive for output
    // we simply use std::strinstream here
    std::stringstream ofs;

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::text_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

    // now we have const char* ofs.str().c_str()
    // transfer those bytes via network
    // read them on the other machine

    gps_position newg;
    {
        // create and open an archive for input
        std::stringstream ifs(the_string_we_read_from_the_network);
        boost::archive::text_iarchive ia(ifs);
        // read class state from archive
        ia >> newg;
        // archive and stream closed when destructors are called
    }
    return 0;
}
] bar.deserialize(stream); // ... Now bar is a copy, via a serial stream of data, of foo.
'; os.write((char*)&data, sizeof(data)); os.write(someNullTerminatedName, strlen(someNullTerminatedName)); os.write(&null, 1); return os; } std::istream& deserialize(std::istream& is) { char buffer[1024]; int i = 0; is.read((char*)&data, sizeof(data)); do { buffer[i] = is.get(); ++i; } while(buffer[i] != '##代码##'); if (someNullTerminatedName != NULL) free(someNullTerminatedName); someNullTerminatedName = (char*)malloc(i); for (i = 0; buffer[i] != '##代码##'; ++i) { someNullTerminatedName[i] = buffer[i]; } return is; } };
"); printMsg(newMsg); char data[PACKETSIZE]; serialize(newMsg, data); MSG* temp = new MSG; deserialize(data, temp); printMsg(temp); return 0; } void serialize(MSG* msgPacket, char *data) { int *q = (int*)data; *q = msgPacket->type; q++; *q = msgPacket->priority; q++; *q = msgPacket->sender; q++; char *p = (char*)q; int i = 0; while (i < BUFSIZE) { *p = msgPacket->message[i]; p++; i++; } } void deserialize(char *data, MSG* msgPacket) { int *q = (int*)data; msgPacket->type = *q; q++; msgPacket->priority = *q; q++; msgPacket->sender = *q; q++; char *p = (char*)q; int i = 0; while (i < BUFSIZE) { msgPacket->message[i] = *p; p++; i++; } } void printMsg(MSG* msgPacket) { cout << msgPacket->type << endl; cout << msgPacket->priority << endl; cout << msgPacket->sender << endl; cout << msgPacket->message << endl; }

回答by rwols

You can just do

你可以做

##代码##

It's up to you to take care of endianness and differences in size of ints and whatnot.

由您来处理字节序和ints大小的差异等等。

Example:

例子:

##代码##

If you have a socket library that exposes its interface via C++ iostreams then you don't even need the stringstream.

如果您有一个通过 C++ iostreams 公开其接口的套接字库,那么您甚至不需要 stringstream。

回答by Nick

You can also have a look at Protocol Buffersfrom Google which is a platform/language independent library for sending data between hosts.

您还可以查看Google 的Protocol Buffers,它是一个独立于平台/语言的库,用于在主机之间发送数据。

However, the paradigm is shifted towards writing the protocol first and then fitting your data structures into it. The advantage of this though is that it forces your software architecture to fit well with simple data types.

然而,范式转向首先编写协议,然后将您的数据结构放入其中。这样做的好处是它迫使你的软件架构很好地适应简单的数据类型。

回答by mkaes

Ok I will take the examplefrom the boost web site as I don't understand what you can not understand from it.
I added some comments and changes to it how you can transfer via network. The network code itself is not in here. For this you can take a look at boost::asio.

好的,我将从boost 网站上举个例子,因为我不明白你不能从中理解什么。
我添加了一些评论和更改,如何通过网络传输。网络代码本身不在这里。为此,您可以查看boost::asio

##代码##

回答by Arthur

If your struct is PODyou can use memcpy:

如果你的结构是POD你可以使用memcpy

::memcpy(data, &your_struct, sizeof(YourStruct)));

::memcpy(data, &your_struct, sizeof(YourStruct)));

and vice versa at reception:

反之亦然:

::memcpy(&your_struct, data, sizeof(YourStruct)));

::memcpy(&your_struct, data, sizeof(YourStruct)));

Where datais a char*. Don't forget you have to Allocate it, making sure it's big enought and delete it at the end.

哪里datachar*. 不要忘记你必须分配它,确保它足够大并在最后删除它。