C++ 中的 Google ProtoBuf 与 C# 中的 Protobuf-net 聊天(UDP)

Googles ProtoBuf on C++ chatting with Protobuf-net on C# (UDP)

关于这两个 Protobuf,我有一个大问题。

我有一个 Server/Client 使用 Googles Protobuf 的 C++ 应用程序。 效果很好。

客户端将数据发送到服务器,服务器应分发此消息 给其他客户。

C++ 客户端是一个纯发送方,将 Protobuf-Struct 打包在一个固定大小 (500 atm) 的字符数组中。

C++ 服务器反序列化它,查找命令(登录注销或给其他人的消息),并且(如果它是消息)将它发送到 C# 客户端。 这也是通过 500 个字符的固定大小来完成的。

这个效果很好。 现在在 C# 方面:

C# 客户端atm 可以使用Protobuf-net 登录和发送消息。即使 Protobuf-Net 将其打包为具有动态大小的字节数组(与 c++ 端的字符数组不同,它是无符号的),这仍然非常有效。 即便如此,服务器也能识别出 Message 并将其打印出来。

但是当服务器从 c++-Client 转发消息时(这是一个奇怪的问题)我在 C# 中遇到了大问题。

注:客户端是Unity3D实现的

Unity 几乎可以正常接收字节数组。 需要注意的一件事是,与服务器发送的消息不同,字节数组是未签名的。这导致 -1 变成 255.

C#-代码:

sock.ReceiveFrom (incoming, ref otherEnd);    
SendPack message;
using(System.IO.MemoryStream ms = 
new System.IO.MemoryStream(incoming)){
    message = ProtoBuf.Serializer.Deserialize<SendPack>(ms);
    print (message);
    ms.Flush();
    ms.Close();
}

这是 C# 客户端。

C++-代码:

char buffer[BUF];
package.serializeToArray(buffer,500);
int n = sendto(sock,buffer,BUF,0,(struct sockaddr*)
&serverAddr,sizeof(serverAddr));

这是 C++ 客户端

C++ 服务器只是将字符数组转发给 C# 客户端, 这与没有序列化部分的 UDP 客户端相同。

我收到如下错误: 原型异常: 源数据中的无效字段:0

或线型无效

编辑: 这是原始文件

syntax = "proto2"; package Messages;

message SendPack {
  required int32 command = 1;
  required string name = 2;
  repeated RobotPart content = 3;

}

message RobotPart {
required float yaw = 1;
required float pitch = 2;
required float roll = 3;
}

对于 C++,我使用普通的 Proto-Compiler 对于 C#,我使用 -Net 编译器创建一个 CS 文件 然后从中构建库,参考 ProtoBuf.dll 统一 然后让预编译器制作一个 Serialize.dll 以包含在 Unity3D

好的,我重新阅读了你的代码更好。我认为问题可能与您处理 c# 服务器的方式有关。我认为您应该尝试这种方法:

MemoryStream stream = new MemoryStream(incoming, false);
ModelSerializer 序列化器 = new ModelSerializer(); message = (SendPack) serializer.Deserialize (stream, incoming, typeof (incoming));

好的。我现在找到了答案。

如果传入消息的长度不是 Protobuf 的确切字节大小(在我的例子中是 500),Protobuf-Net 就会有真正的问题。

我这样修改了我的 C++ 服务器:

int size = package.ByteSize();
char message[size];
package.SerializeToArray(message,size);

然后用这个尺寸发送。

正如我在我的 OP 中提到的,C++ 版本可以 处理打包到固定大小数组中的消息 并对其进行解码。

现在在 C# 部分我需要做一些工作。

我仍然收到一条消息并将其放入固定大小的字节数组中。 如果我只使用未初始化的数组,我会出错。

int s = sock.ReceiveFrom (incoming, ref otherEnd);
SendPack message = new SendPack();
using(System.IO.MemoryStream ms = new System.IO.MemoryStream(incoming,0,s)){
    SendPackSerializer sps = new SendPackSerializer();
    message = (SendPack)sps.Deserialize(ms,null,typeof(SendPack));
    print (message);
    ms.Flush();
    ms.Close();
}