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
好的,我把你的代码重读了一遍。我认为问题可能与你处理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();
}