C++中protobuf消息的长度前缀

Length prefix for protobuf messages in C++

本文关键字:前缀 消息 protobuf C++      更新时间:2023-10-16

我正在使用protobuf序列化通过C++中的套接字连接发送的消息。对于通信,我想在消息包中添加一个标头,指示消息的长度。你对这个实现有什么看法?我做了一些研究,这就是我所做的。

有更好的方法吗?这种实现会引起任何麻烦吗?我知道API支持Java,但遗憾的是不支持C++。

bool send_message(int socket, my_protobuf::Message message)
{
  google::protobuf::uint32 message_length = message.ByteSize();
  int prefix_length = sizeof(message_length);
  int buffer_length = prefix_length + message_length;
  google::protobuf::uint8 buffer[buffer_length];
  google::protobuf::io::ArrayOutputStream array_output(buffer, buffer_length);
  google::protobuf::io::CodedOutputStream coded_output(&array_output);
  coded_output.WriteLittleEndian32(message_length);
  message.SerializeToCodedStream(&coded_output);
  int sent_bytes = write(socket, buffer, buffer_length);
  if (sent_bytes != buffer_length) {
    return false;
  }
  return true;
}
bool recv_message(int socket, my_protobuf::Message *message)
{
  google::protobuf::uint32 message_length;
  int prefix_length = sizeof(message_length);
  google::protobuf::uint8 prefix[prefix_length];
  if (prefix_length != read(socket, prefix, prefix_length)) {
    return false;
  }
  google::protobuf::io::CodedInputStream::ReadLittleEndian32FromArray(prefix,
      &message_length);
  google::protobuf::uint8 buffer[message_length];
  if (message_length != read(socket, buffer, message_length)) {
    return false;
  }
  google::protobuf::io::ArrayInputStream array_input(buffer, message_length);
  google::protobuf::io::CodedInputStream coded_input(&array_input);
  if (!message->ParseFromCodedStream(&coded_input)) {
    return false;
  }
  return true;
}

使用variant(例如WriteVarint32)而不是fixed32(在有WriteLittleEndian32的情况下)更为常见,但通过前缀长度来界定protobuf流的做法是合理的。