谷歌上的Googles ProtoBuf与C#(UDP)上的Protobuf-net聊天

时间:2016-06-28 20:34:16

标签: c# c++ udp protocol-buffers protobuf-net

我对这两个Protobufs都有一个很大的问题。

我使用Googles Protobuf在C ++上有一个服务器/客户端应用程序。 它运作得很好。

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

C ++客户端是一个纯粹的发送者,将Protobuf-Struct打包成一个固定大小(500个大气压)的Char-Array。

C ++服务器对其进行反序列化,查找命令(登录注销或向其他人发送消息),以及(如果是消息)将其发送到C#-Client。 这也是通过固定大小的500个字符来完成的。

这很有效。 现在在C#方面:

C#client atm可以使用Protobuf-net登录并发送消息。尽管Protobuf-Net将它包装在一个字节数组(与c ++-side上的字符数组不同,它是无符号的)并且具有动态大小,但它的工作非常出色。 即使如此,服务器也会识别该消息并将其打印出来。

但是当服务器从c ++转发消息时,这是一个非常棘手的问题 - 客户端我在C#中遇到了大问题。

注意:客户端在Unity3D中实现。

Unity收到Byte-Array几乎没问题。 需要注意的一点是,与服务器发送的消息不同,字节数是无符号的。这导致-1变为255.

C#-Code:

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

这是C#客户端。

C ++ - 代码:

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 ++ - 客户端

C ++ - Server只是将char-Array转发给C#-client, 这与没有serialize-part的UDP-Client相同。

我得到的错误如下: ProtoException: 源数据中的字段无效:0

或Invalide wire-type

编辑: 这是Proto-File

{{1}}

对于C ++,我使用普通的Proto-Compiler 对于C#,我使用-Net编译器来创建CS文件 然后从它构建libary,参考ProtoBuf.dll进行统一 然后让预编译器将Serialize.dll包含在Unity3D中

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

如果传入的消息具有固定长度(在我的情况下为500),如果它不是Protobuf的确切字节大小,则Protobuf-Net存在实际问题。

我用这种方式修改了我的C ++ - 服务器:

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

然后以这个尺寸发送它。

正如我在OP中提到的,C ++版本可以 处理打包到修复大小的数组中的消息 并解码它们。

现在关于C#-Part我需要做一些工作。

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

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();
}