[英]Typecasting from byte[] to struct
I'm currently working on a small C++ project where I use a client-server model someone else built. 我目前正在研究一个小型C ++项目,在这里我使用别人构建的客户端-服务器模型。 Data gets sent over the network and in my opinion it's in the wrong order.
数据是通过网络发送的,我认为顺序错误。 However, that's not something I can change.
但是,这不是我可以更改的。
Example data stream (simplified): 示例数据流(简化):
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)
I can represent this specific stream as : 我可以将此特定流表示为:
struct test {
short sh1;
short sh2;
char abc[4];
bool bool1;
bool bool2;
}
And I can typecast it with test *t = (test*)stream;
我可以使用
test *t = (test*)stream;
进行类型转换test *t = (test*)stream;
However, the char* has a variable length. 但是,char *具有可变长度。 It is, however, always null terminated.
但是,它始终为null终止。
I understand that there's no way of actually casting the stream to a struct, but I was wondering whether there would be a better way than struct test() { test(char* data) { ... }}
(convert it via the constructor) 我了解没有办法将流实际转换为结构,但是我想知道是否有比
struct test() { test(char* data) { ... }}
(通过构造函数转换struct test() { test(char* data) { ... }}
更好的方法)
This is called Marshalling or serialization . 这称为编组或序列化 。
What you must do is read the stream one byte at a time (or put all in a buffer and read from that), and as soon as you have enough data for a member in the structure you fill it in. 您必须做的是一次读取一个字节流(或将其全部放入缓冲区并从中读取),并且一旦有足够的数据供结构中的成员使用,就填充它。
When it comes to the string, you simply read until you hit the terminating zero, and then allocate memory and copy the string to that buffer and assign it to a pointer in the struct. 当涉及到字符串时,您只需读取直到达到终止零,然后分配内存并将该字符串复制到该缓冲区,然后将其分配给该结构中的指针即可。
Reading strings this way is simplest and most effective if you have of the message in a buffer already, because then you don't need a temporary buffer for the string. 如果您已经将消息存储在缓冲区中,则以这种方式读取字符串是最简单且最有效的,因为这样就不需要为该字符串设置临时缓冲区。
Remember though, that with this scheme you have to manually free the memory containing the string when you are done with the structure. 但是请记住,使用此方案时,必须在完成结构后手动释放包含字符串的内存。
Just add a member function that takes in the character buffer(function input parameter char *
) and populates the test
structure by parsing it. 只需添加一个成员函数,该成员函数接受字符缓冲区(函数输入参数
char *
)并通过对其进行分析来填充test
结构。
This makes it more clear and readable as well. 这也使它更清晰易读。
If you provide a implicit conversion constructor then you create a menace which will do the conversion when you least expect it. 如果提供隐式转换构造函数,则会创建一个威胁,它将在您最不期望的时候进行转换。
When reading variable length data from a sequence of bytes, you shouldn't fit everything into a single structure or variable. 从字节序列读取可变长度数据时,不应将所有内容都放入单个结构或变量中。 Pointers are also used to store this variable length.
指针还用于存储此可变长度。
The following suggestion, is not tested: 以下建议未经测试:
// 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()
Cheers. 干杯。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.