google ProtoBuf在c++上与ProtoBuf -net在c# (UDP)上聊天

本文关键字:ProtoBuf UDP 聊天 -net c++ 上与 google | 更新日期: 2023-09-27 17:52:43

我有一个关于这两个Protobufs的大问题。

我有一个服务器/客户端应用程序在c++上使用谷歌的Protobuf。它工作得很好。

客户端将数据发送给服务器,服务器应该分发此消息

c++客户端是一个纯粹的发送者,将Protobuf-Struct封装在一个固定大小(500 atm)的Char-Array中。

c++服务器对它进行反序列化,查找命令(登录登出或给其他人的消息),并且(如果是消息)将其发送给c#客户端。这也可以通过固定的500个字符来实现。

这工作得很好。现在在c#端:

c#客户端可以登录并使用Protobuf-net发送消息。尽管Protobuf-Net将其打包为动态大小的字节数组(与c++端char数组不同,字节数组是无符号的),但这种方法仍然非常出色。即使这样,服务器也能识别出消息并将其打印出来。

但是(这是一个可怕的问题)当服务器从c++客户端转发消息时,我在c#中遇到了大问题。

说明:客户端是在Unity3D中实现的。

Unity接收Byte-Array几乎没问题。需要注意的一点是,字节数组与服务器发送的消息不同,是无符号的。这导致-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++服务器只是将char-Array转发给c#客户端,这与没有序列化部分的UDP-Client相同。

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

或invalid wire-type

编辑:这是原始文件

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用于unity然后让预编译器制作一个Serialize.dll来包含在Unity3D

google ProtoBuf在c++上与ProtoBuf -net在c# (UDP)上聊天

好的,我把你的代码重读了一遍。我认为问题可能与你处理c#服务器的方式有关。我认为你应该试试这个方法:

MemoryStream stream = new MemoryStream(incoming, false);
ModelSerializer serializer = new ModelSerializer();message = (SendPack)序列化器。反序列化(流,传入,typeof(传入));

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

Protobuf- net有真正的问题,如果传入的消息有一个固定的长度(在我的情况下500),如果它不是Protobuf的确切字节大小。

我这样修改了我的c++ -Server:

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