Serialize Strings, ints and floats to character arrays for networking WITHOUT LIBRARIES

后端 未结 4 802
我寻月下人不归
我寻月下人不归 2020-12-29 11:48

I want to transmit data over the network, but I don\'t want to use any foreign libraries (Standard C/C++ is ok).

for example:

unsigned int x = 123;
c         


        
相关标签:
4条回答
  • 2020-12-29 12:15

    Ah, you want to serialize primitive data types! In principle, there are two approaches: The first one is, that you just grab the internal, in-memory binary representation of the data you want to serialize, reinterpret it as a character, and use that as you representation:

    So if you have a:

    double d;

    you take the address of that, reinterpret that pointer as a pointer to character, and then use these characters:

    double *pd=&d;
    char *pc = reinterpret_cast<char*>(pd); 
    for(size_t i=0; i<sizeof(double); i++) 
    {
       char ch = *pc;   
       DoSomethingWith(ch);   
       pc++;
    }
    

    This works with all primitive data types. The main problem here is, that the binray representation is implementation dependent (mainly CPU dependent). (And you will run into subtle bugs when you try doing this with IEEE NANs...).

    All in all, this approach is not portable at all, as you have no control at all over the representation of your data.

    The second approach is, to use a higher-level representation, that you yourself have under control. If performance is not an issue, you could use std::strstream and the >> and << operators to stream primitive C type variables into std::strings. This is slow but easy to read and debug, and very portable on top of it.

    0 讨论(0)
  • 2020-12-29 12:20

    This discussion seems relevant to your question, but it uses boost serialization API

    0 讨论(0)
  • 2020-12-29 12:23

    Something like the code below would do it. Watch out for problems where sizeof(unsigned int) is different on different systems, those will get you. For things like this you're better off using types with well-defined sizes, like int32_t. Anyway...

    unsigned int x = 123;
    char y[3] = {'h', 'i', '\0'};
    float z = 1.23f;
    
    // The buffer we will be writing bytes into
    unsigned char outBuf[sizeof(x)+sizeof(y)+sizeof(z)];
    
    // A pointer we will advance whenever we write data
    unsigned char * p = outBuf;
    
    // Serialize "x" into outBuf
    unsigned int32_t neX = htonl(x);
    memcpy(p, &neX, sizeof(neX));
    p += sizeof(neX);
    
    // Serialize "y" into outBuf
    memcpy(p, y, sizeof(y));
    p += sizeof(y);
    
    // Serialize "z" into outBuf
    int32_t neZ = htonl(*(reinterpret_cast<int32_t *>(&z)));
    memcpy(p, &neZ, sizeof(neZ));
    p += sizeof(neZ);
    
    int resultCode = send(mySocket, outBuf, p-outBuf, 0);
    [...]
    

    ... and of course the receiving code would do something similar, except in reverse.

    0 讨论(0)
  • 2020-12-29 12:38

    What exactly is your goal? And what exactly are the means you're willing to use?

    If you just want to get the job done with one particular compiler on one particular computer, then the fastest and easiest, but also dirtiest, solution is, to use a union. You define a struct that has your items as members and merge that with the character array. You need to tell the compiler to pack the members really tightly, something along the lines of #pragma pack(1), and your problem is solved. You just store the three values in the members, and then look at it as a character array.

    If the machine is little endian, and you need big endian ints / floats, you just swap the relevant characters.

    But there are at least another dozen solutions that come to mind if you have other goals, like portability, non-standard byte order, sizeof(int) !=4, float not stored in IEEE format internally, etc.

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