struct headers 与 vec<char> 的相互转换
Converting struct headers to and from vec<char>
我正在尝试用较小的 char* 消息与它们各自的 header 交错打包一个消息缓冲区向量。这些 header 从结构中转换为 char*。接收者通过从 header 跳到 header 来解包缓冲区。使用 header,他们可以识别相应消息的大小以及下一个 header 开始的位置。
struct header_t {
uint64_t src : 16;
uint64_t dst : 16;
uint64_t len : 32;
} __attribute__((packed));
这是一个 fixed-size header 结构。使用 using 将它们转换为向量:
std::vector<char> pack_header(int src, int dest, int data_size){
header_t hdr_struct{(uint64_t)src, (uint64_t)dest, (uint64_t)data_size};
char* ptr = reinterpret_cast<char*>(&hdr_struct);
std::vector<char> hdr = std::vector<char>(ptr, ptr + sizeof(header_t));
return hdr;
}
主程序通过将 3 条消息及其各自的 header 附加到缓冲区来打包它们。为简单起见,我在这里也调用了解包函数,但在实际应用程序中,缓冲区是在其他进程中解包的。
int main()
{
auto header1 = pack_header(2, 4, 43);
auto header2 = pack_header(2, 4, 29);
auto header3 = pack_header(2, 4, 23);
//Test messages of the given sizes
char* data1 = new char[43]();
char* data2 = new char[29]();
char* data3 = new char[23]();
//messages interleaved with headers
std::vector<char> buffer;
buffer.insert(buffer.end(), header1.begin(),header1.end());
buffer.insert(buffer.end(), data1, data1+43);
buffer.insert(buffer.end(), header2.begin(),header2.end());
buffer.insert(buffer.end(), data2, data2+29);
buffer.insert(buffer.end(), header3.begin(),header3.end());
buffer.insert(buffer.end(), data3, data3+23);
unpack(buffer);
return 0;
}
此解包函数通过以 header 长度(8 字节)+ 消息长度的大小为步长迭代缓冲区。
void unpack(std::vector<char> &stream)
{
char* bitr = &stream[0];
int step =0;
std::vector<header_t*> hdr_stream;
while(step <= stream.size())
{
std::cout<<"\nstep: "<<step;
header_t header;
memcpy(&header, bitr, sizeof(header_t));
std::cout<<"\nlen_after : "<<header.len<<"\n";
step+=header.len + sizeof(header_t);
bitr+=step;
}
}
解包函数正确地逐步处理了前 2 条消息,但之后就迷路了,并且没有推断出 header。输出如下所示:
step: 0
message length : 43
step: 51
message length : 29
step: 88
message length : 0
step: 96
message length : 0
step: 104
message length : 0
step: 112
message length : 0
无法从第二条消息后的 header 中正确推断大小的任何原因。它只是将大小读取为 0 并跨过 headers 而不是 header + 消息。
每次迭代,您都会将 step
增加当前数据包的大小。它是下一个数据包开始位置 stream
的索引。但是,您将此索引添加到 bitr
,导致未定义的行为,因为 bitr
已增加到缓冲区末尾。
你得到的是:
start of 1st loop: bitr = 0
start of 2nd loop: bitr = 51 (size of first packet)
start of 3rd loop: bitr = 139 (51 + 51 + 37, 2 * size of first packet + size of second packet)
你想要做的是增加 bitr
与你增加 step
(bitr+=header.len + sizeof(header_t);
) 相同的数量,或者将 set bitr
设置为新计算的索引 (bitr = &stream[step];
).
我正在尝试用较小的 char* 消息与它们各自的 header 交错打包一个消息缓冲区向量。这些 header 从结构中转换为 char*。接收者通过从 header 跳到 header 来解包缓冲区。使用 header,他们可以识别相应消息的大小以及下一个 header 开始的位置。
struct header_t {
uint64_t src : 16;
uint64_t dst : 16;
uint64_t len : 32;
} __attribute__((packed));
这是一个 fixed-size header 结构。使用 using 将它们转换为向量:
std::vector<char> pack_header(int src, int dest, int data_size){
header_t hdr_struct{(uint64_t)src, (uint64_t)dest, (uint64_t)data_size};
char* ptr = reinterpret_cast<char*>(&hdr_struct);
std::vector<char> hdr = std::vector<char>(ptr, ptr + sizeof(header_t));
return hdr;
}
主程序通过将 3 条消息及其各自的 header 附加到缓冲区来打包它们。为简单起见,我在这里也调用了解包函数,但在实际应用程序中,缓冲区是在其他进程中解包的。
int main()
{
auto header1 = pack_header(2, 4, 43);
auto header2 = pack_header(2, 4, 29);
auto header3 = pack_header(2, 4, 23);
//Test messages of the given sizes
char* data1 = new char[43]();
char* data2 = new char[29]();
char* data3 = new char[23]();
//messages interleaved with headers
std::vector<char> buffer;
buffer.insert(buffer.end(), header1.begin(),header1.end());
buffer.insert(buffer.end(), data1, data1+43);
buffer.insert(buffer.end(), header2.begin(),header2.end());
buffer.insert(buffer.end(), data2, data2+29);
buffer.insert(buffer.end(), header3.begin(),header3.end());
buffer.insert(buffer.end(), data3, data3+23);
unpack(buffer);
return 0;
}
此解包函数通过以 header 长度(8 字节)+ 消息长度的大小为步长迭代缓冲区。
void unpack(std::vector<char> &stream)
{
char* bitr = &stream[0];
int step =0;
std::vector<header_t*> hdr_stream;
while(step <= stream.size())
{
std::cout<<"\nstep: "<<step;
header_t header;
memcpy(&header, bitr, sizeof(header_t));
std::cout<<"\nlen_after : "<<header.len<<"\n";
step+=header.len + sizeof(header_t);
bitr+=step;
}
}
解包函数正确地逐步处理了前 2 条消息,但之后就迷路了,并且没有推断出 header。输出如下所示:
step: 0
message length : 43
step: 51
message length : 29
step: 88
message length : 0
step: 96
message length : 0
step: 104
message length : 0
step: 112
message length : 0
无法从第二条消息后的 header 中正确推断大小的任何原因。它只是将大小读取为 0 并跨过 headers 而不是 header + 消息。
每次迭代,您都会将 step
增加当前数据包的大小。它是下一个数据包开始位置 stream
的索引。但是,您将此索引添加到 bitr
,导致未定义的行为,因为 bitr
已增加到缓冲区末尾。
你得到的是:
start of 1st loop: bitr = 0
start of 2nd loop: bitr = 51 (size of first packet)
start of 3rd loop: bitr = 139 (51 + 51 + 37, 2 * size of first packet + size of second packet)
你想要做的是增加 bitr
与你增加 step
(bitr+=header.len + sizeof(header_t);
) 相同的数量,或者将 set bitr
设置为新计算的索引 (bitr = &stream[step];
).