Flatbuffers 如何在一条消息中发送 uint16_t header、size_t body 大小和 uint8_t buffer

问题描述 投票:0回答:2

我正在使用 FlatBuffersBoost ASIO

我想按照以下顺序形成一条消息:

  1. uint16_t 标头标识符。 (固定尺寸留言)
  2. size_t 身体尺寸 <- so the reading part can know how long is the message that it needs to read. (fixed size message)
  3. Flatbuffers 对象。 (动态大小消息,大小以2发送)

因此,对于前两个,我是如何将它们组合起来发送的:

size_t const header_length = 8;
size_t const body_size_b = 8;

ServerOpcode opc;
opc = ServerOpcode::SMSG_LOGIN_REQUEST_RESPONSE_TEST;
std::string header = std::to_string(opc);
flatbuffers::FlatBufferBuilder builder;
auto name = builder.CreateString("Orc MONSTER");
auto accountRole = Vibranium::CreateAccountRole_Packet(builder,1,name);
builder.Finish(accountRole);
size_t size = builder.GetSize();
uint8_t *buf = builder.GetBufferPointer();

std::array<char, header_length + body_size_b> buffer{};
std::copy(header.begin(), header.end(), buffer.begin());
std::copy(std::to_string(size).begin(), std::to_string(size).end(), buffer.begin() + header_length);
// How can I add builder here at third place ?
boost::asio::write(s, boost::asio::buffer(buffer,sizeof(buffer)));

我不知道如何在前两个缓冲区之后附加 Flatbuffers 缓冲区。

我的问题是:

如何将这三者按顺序统一并集中发送

boost::asio::write

c++ boost-asio flatbuffers
2个回答
1
投票

您不需要 1) 和 2)。要获得 1),请在架构中声明

file_identifier
,然后将该标识符传递给
Finish
。要获得 2),请使用
FinishSizePrefixed
。所有这些都在您仍然不想阅读的文档中。

再说一次,这是二进制格式,所以我不确定你在做什么

std::to_string
但它不会起作用。你只需要写出
buf
的内容即可。我不知道如何将它与 Boost 一起使用。


0
投票

正如另一个答案所指出的,您可以使用 file_identifier 和 size 前缀来确定传入消息的类型和大小。

namespace ns;

table Message {
  content: string;
}

file_identifier "MESG";

root_type Message;

假设您已经定义了此架构。要构建带有大小前缀和标识符的消息,您需要使用

builder.FinishSizePrefixed(message, ns::MessageIdentifier());

flatbuffers::DetachedBuffer build_message(const std::string& content)
{
  flatbuffers::FlatBufferBuilder builder;
  auto message = ns::CreateMessage(builder, builder.CreateString(content));
  builder.FinishSizePrefixed(message, ns::MessageIdentifier());
  return builder.Release();
}

使用 asio 发送消息:

auto message = build_message("Hello World");

asio::error_code ec;
asio::write(socket, asio::buffer(message.data(), message.size()), ec);

在应用程序的接收端,您可以使用

flatbuffers::GetSizePrefixedBufferLength
从数据的前 4 个字节中获取消息的大小。阅读整条消息后,您可以使用
flatbuffers::GetBufferIdentifier
确定消息类型。

std::vector<uint8_t> buffer;

// read size
co_await asio::async_read(socket, asio::dynamic_buffer(buffer, 4), asio::use_awaitable);

auto size = flatbuffers::GetSizePrefixedBufferLength(buffer.data());

// read message
co_await asio::async_read(socket, asio::dynamic_buffer(buffer, size), asio::use_awaitable);

std::string type(
    flatbuffers::GetBufferIdentifier(buffer.data(), true),
    flatbuffers::FlatBufferBuilder::kFileIdentifierLength);

一旦您知道消息的类型,您就可以验证它并使用其模式生成的函数解析您的消息。

auto verifier = flatbuffers::Verifier(buffer.data(), buffer.size());
auto is_valid_message = ns::VerifySizePrefixedMessageBuffer(verifier);
auto message = net::GetSizePrefixedMessage(buffer.data());

message->content(); // Hello World
© www.soinside.com 2019 - 2024. All rights reserved.