c # — получение сообщения Protobuf3 по сети

Я использую Protobuf3 с c # для моего клиента & c ++ для моего сервера, где .proto генерируются из соответствующего компилятора protoc3. Я новичок в использовании буферов протокола Google, где в настоящее время пытаюсь выяснить, как повторно проанализировать полученные на моем сервере байты, которые были отправлены с моего клиента, чтобы превратить его в исходный google :: protobuf :: Message Объект на моем сервере C ++.

Мой клиент отправляет CodedOutputStream в C #:

public PacketHandler()
{
m_client  = GetComponent<ClientObject>();
m_packet  = new byte[m_client.GetServerConnection().GetMaxPacketSize()];
m_ostream = new BinaryWriter(new MemoryStream(m_packet));
}

public void DataToSend(IMessage message)
{
CodedOutputStream output = new CodedOutputStream(m_ostream.BaseStream, true);
output.WriteMessage(message);
output.Flush();
m_client.GetServerConnection().GetClient().Send(m_packet, message.CalculateSize());
}

Кажется, это работает, сообщение, которое отправляется прямо сейчас, представляет собой простое сообщение Ping, которое выглядит так:

// Ping.proto
syntax = "proto3";
package server;

import "BaseMessage.proto";

message Ping {
base.BaseMessage base = 1;
}

message Pong {
base.BaseMessage base = 1;
}

Мой BaseMessage выглядит так:

// BaseMessage.proto
syntax = "proto3";

package base;

message BaseMessage {
uint32 size = 1;
}

Мой план состоит в том, чтобы, надеюсь, расширить все мои сообщения из BaseMessage, чтобы в конечном итоге можно было идентифицировать конкретное сообщение. Как только я получу разбор & повторный разбор разобрался.

Полученное сообщение, которое я получаю на стороне сервера c ++, выглядит следующим образом: \ u0004 \ n \ u0002 \ b

При получении сообщения я пытаюсь повторно проанализировать, используя объект CodedInputStream, пытаясь проанализировать полученные байты.

PacketHandler::PacketHandler(QByteArray& packet, const Manager::ClientPtr client) :
m_packet(packet),
m_client(client)
{
//unsigned char buffer[512] = { 0 };
unsigned char data[packet.size()] = { 0 };
memcpy(data, packet.data(), packet.size());

google::protobuf::uint32 msgSize;
google::protobuf::io::CodedInputStream inputStream(data, packet.size());
//inputStream.ReadVarint32(&msgSize);
//inputStream.ReadRaw(buffer, packet.size());
server::Ping pingMsg;
pingMsg.ParseFromCodedStream(&inputStream);
qDebug() << pingMsg.base().size();
}

Вот где я немного не уверен в том, какой процесс необходимо выполнить, чтобы повторно проанализировать сообщение в конкретном сообщении. Я считаю, что если я использую BaseMessage, который расширяет все сообщения, которые позволят мне идентифицировать конкретное сообщение, чтобы я знал, какое из них создать. Однако в этом текущем тесте, где я знаю, что это будет сообщение Ping, ParseFromCodedStream, похоже, не создает исходное сообщение. Мои рассуждения основаны на том, что во время моего qDebug () pingMsg.base (). Size () не является правильным значением, которое было установлено во время фазы отправки в моем клиенте c #.

0

Решение

Я смог решить эту проблему, увеличив число отправленных байтов на +1.

public void DataToSend(IMessage message)
{
CodedOutputStream output = new CodedOutputStream(m_ostream.BaseStream, true);
output.WriteMessage(message);
output.Flush();
(m_ostream.BaseStream as MemoryStream).SetLength(0); // reset stream for next packet(s)
m_client.GetServerConnection().GetClient().Send(m_packet, message.CalculateSize() + 1);
}

Я все еще немного подозреваю, почему мне нужно добавить один. Я думаю, это должно быть связано с нулевым терминатором. Однако до этого без этого добавления мое сообщение будет выглядеть так: #\u0012!\n\u001Ftype.googleapis.com/server.Pin

Затем с добавлением все, что он делает, это добавляет правильное сообщение: #\u0012!\n\u001Ftype.googleapis.com/server.Ping

Кроме того, во время этого процесса я выяснил, как классифицировать мои сообщения, используя protobuf3 Любой тип. Где теперь мое BaseMessage определяется как:

syntax = "proto3";

package base;

import "google/protobuf/any.proto";

message BaseMessage {
uint32 size = 1;
google.protobuf.Any msg = 2;
}

Что позволяет мне поместить любой вид google :: protobuf :: Message в поле msg, где на ParsingFromCodedStream я могу проверить, является ли это конкретное сообщение.

PacketHandler::PacketHandler(QByteArray& packet, const Manager::ClientPtr client) :
m_packet(packet),
m_client(client)
{
unsigned char data[packet.size()] = { 0 };
memcpy(data, packet.data(), packet.size());

google::protobuf::io::CodedInputStream inputStream(data, packet.size());
// read the prefixed length of the message & discard
google::protobuf::uint32 msgSize;
inputStream.ReadVarint32(&msgSize);
// -----
// collect the BaseMessage & execute functionality based on type_url
base::BaseMessage msg;
if (!msg.ParseFromCodedStream(&inputStream))
{
qDebug() << msg.DebugString().c_str();
return;
}

if (msg.msg().Is<server::Ping>())
{
server::Ping pingMsg;
msg.msg().UnpackTo(&pingMsg);
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]