Serialization of struct

后端 未结 5 1142
野性不改
野性不改 2020-11-30 05:12

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 * keepin

相关标签:
5条回答
  • 2020-11-30 05:45

    Following example shows a simplest way to serialize struct into char array and de-serialize it.

    #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\0");
        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;
    }
    
    0 讨论(0)
  • 2020-11-30 05:46

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

    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.

    0 讨论(0)
  • 2020-11-30 05:49

    Ok I will take the example from 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.

    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;
    }
    
    0 讨论(0)
  • 2020-11-30 05:57

    You can just do

    struct MyStruct {
    
        int data;
        char* someNullTerminatedName; // Assuming not larger than 1023 chars
    
        std::ostream& serialize(std::ostream& os) const {
            char null = '\0';
            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] != '\0');
            if (someNullTerminatedName != NULL) free(someNullTerminatedName);
            someNullTerminatedName = (char*)malloc(i);
            for (i = 0; buffer[i] != '\0'; ++i) {
                someNullTerminatedName[i] = buffer[i];
            }
            return is;
        }
    };
    

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

    Example:

    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 \0 ]
    bar.deserialize(stream);
    // ... Now bar is a copy, via a serial stream of data, of foo.
    

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

    0 讨论(0)
  • 2020-11-30 06:00

    If your struct is POD you can use memcpy:

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

    and vice versa at reception:

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

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

    0 讨论(0)
提交回复
热议问题