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];).