从byte []到struct的类型转换

时间:2011-11-10 16:16:55

标签: c++ networking casting

我目前正在开发一个小型C ++项目,我使用其他人构建的客户端 - 服务器模型。数据通过网络发送,在我看来,它的顺序错误。但是,这不是我可以改变的。

示例数据流(简化):

0x20 0x00 (C++: short with value 32)
0x10 0x35 (C++: short with value 13584)
0x61 0x62 0x63 0x00 (char*: abc)
0x01 (bool: true)
0x00 (bool: false)

我可以将此特定流表示为:

struct test {
    short sh1;
    short sh2;
    char abc[4];
    bool bool1;
    bool bool2;
}

我可以使用test *t = (test*)stream;对其进行类型转换。但是,char *具有可变长度。但是,它始终为空终止。

我知道实际上没有办法将流转换为结构体,但我想知道是否有比struct test() { test(char* data) { ... }}更好的方法(通过构造函数转换它)

3 个答案:

答案 0 :(得分:3)

这称为Marshallingserialization

你必须做的是一次一个字节地读取流(或将所有数据放入缓冲区并从中读取),并且只要有足够的数据用于结构中的成员,就可以填写它。

当涉及到字符串时,您只需读取直到达到终止零,然后分配内存并将字符串复制到该缓冲区并将其分配给结构中的指针。

如果你已经在缓冲区中有了消息,那么以这种方式读取字符串是最简单和最有效的,因为那时你不需要字符串的临时缓冲区。

请记住,使用此方案时,您必须在完成结构后手动释放包含字符串的内存。

答案 1 :(得分:2)

只需添加一个接收字符缓冲区的成员函数(函数输入参数char *)并通过解析填充test结构。
这使它更加清晰和可读。

如果您提供隐式转换构造函数,那么您将创建一个威胁,它会在您最不期望的时候进行转换。

答案 2 :(得分:0)

从字节序列中读取可变长度数据时, 你不应该把所有东西都放在一个结构或变量中。 指针也用于存储这个可变长度。

以下建议未经过测试:

// data is stored in memory,
// in a different way,
// NOT as sequence of bytes,
// as provided
struct data {
    short sh1;
    short sh2;
    int abclength;
    // a pointer, maybe variable in memory !!!
    char* abc;
    bool bool1;
    bool bool2;
};

// reads a single byte
bool readByte(byte* MyByteBuffer)
{
    // your reading code goes here,
    // character by character, from stream,
    // file, pipe, whatever.
    // The result should be true if not error,
    // false if cannot rea anymore
}

// used for reading several variables,
// with different sizes in bytes
int readBuffer(byte* Buffer, int BufferSize)
{
    int RealCount = 0;

    byte* p = Buffer;

    while (readByte(p) && RealCount <= BufferSize)
    {
        RealCount++
        p++;
    }

    return RealCount;
}

void read()
{
    // real data here:
    data Mydata;

    byte MyByte = 0;

    // long enough, used to read temporally, the variable string
    char temp[64000];
    // fill buffer for string with null values
    memset(temp, '\0', 64000);

    int RealCount = 0;

    // try read "sh1" field
    RealCount = (readBuffer(&(MyData.sh1), sizeof(short)));
    if (RealCount == sizeof(short))
    {
        // try read "sh2" field
        RealCount = readBuffer(&(MyData.sh2), sizeof(short));       
        if (RealCount == sizeof(short))
        {
            RealCount = readBuffer(temp, 64000);
            if (RealCount > 0)
            {
                // store real bytes count
                MyData.abclength = RealCount;
                // allocate dynamic memory block for variable length data
                MyData.abc = malloc(RealCount);
                // copy data from temporal buffer into data structure plus pointer
                // arrays in "plain c" or "c++" doesn't require the "&" operator for address:
                memcpy(MyData.abc, temp, RealCount);

                // comented should be read as:
                //memcpy(&MyData.abc, &temp, RealCount);

                // continue with rest of data
                RealCount = readBuffer(&(MyData.bool1), sizeof(bool));
                if (RealCount > 0)
                {
                    // continue with rest of data
                    RealCount = readBuffer(&(MyData.bool2), sizeof(bool));
                }
            }
        }
    }
} // void read()

干杯。