我正在使用 FlatBuffers 和 Boost ASIO
我想按照以下顺序形成一条消息:
因此,对于前两个,我是如何将它们组合起来发送的:
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
?
您不需要 1) 和 2)。要获得 1),请在架构中声明
file_identifier
,然后将该标识符传递给 Finish
。要获得 2),请使用 FinishSizePrefixed
。所有这些都在您仍然不想阅读的文档中。
再说一次,这是二进制格式,所以我不确定你在做什么
std::to_string
但它不会起作用。你只需要写出buf
的内容即可。我不知道如何将它与 Boost 一起使用。
正如另一个答案所指出的,您可以使用 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