Googles ProtoBuf on C++ chatting with Protobuf
I have a big problem concerning those both Protobufs.
I have a Server/Client Application on C++ using Googles Protobuf. It works quite well.
The Client sends the Data to the Server which should distribute this Message to the other Clients.
The C++ Client is a pure sender, packing the Protobuf-Struct in a Char-Array with fixed size (500 atm).
The C++ Server deserializes it, looks for the Command (Login Logout or a Message to others), and (if its a Message) sends it to the C#-Client. This is done also by a fixed size of 500 chars.
This works quite well. Now on the C# side:
The C# client atm can log in and send Messages with Protobuf-net. This works quite brilliant even though Protobuf-Net packs it in a byte-Array (which is unsigned unlike the char-array on c++-Side) with dyanamic size. Even so the server recognizes the Message and prints it out.
BUT (and here is the freaking problem) when the server forwards a message from the c++-Client I get big problems in C#.
For the Note: The client is implemented in Unity3D.
Unity receives the Byte-Array almost fine. One thing to note is that the Byte-Array is unsigned unlike the Message sent by the server. This leads to -1 become 255.
C#-Code:
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();
}
This is the C# Client.
C++-Code:
char buffer[BUF];
package.serializeToArray(buffer,500);
int n = sendto(sock,buffer,BUF,0,(struct sockaddr*)
&serverAddr,sizeof(serverAddr));
This is the C++-Client
The C++-Server just forwards the char-Array to the C#-client, which is the same as the UDP-Client without the serialize-part.
I Get Errors like: ProtoException: Invalid field in source data: 0
or Invalide wire-type
edit: This is the Proto-File
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;
}
For C++ I use the normal Proto-Compiler For C# I use -Net compiler to create a CS-File then Build libary from it, with reference to ProtoBuf.dll for unity and then let the precompiler make a Serialize.dll to include in Unity3D
Ok, I reread your code better. I think the problem may be related on the way you handle the c# server. I think you should try this approach:
MemoryStream stream = new MemoryStream(incoming, false);
ModelSerializer serializer = new ModelSerializer(); message = (SendPack) serializer.Deserialize (stream, incoming, typeof (incoming));
All right. I found the Answer now.
Protobuf-Net has real problems if the incoming Message has a fixed length (in my case 500) if its not the exact byte size of the Protobuf.
I modified my C++-Server this way:
int size = package.ByteSize();
char message[size];
package.SerializeToArray(message,size);
And then send it with this size.
As I mentioned in my OP, the C++ version can handle messages that are packed into fix sized arrays and decode them.
Now on the C#-Part I need to do a little work around.
I still receive a message and put it in a fix sized byte-array. If I just use an uninitialized array, I get errors.
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();
}
链接地址: http://www.djcxy.com/p/42560.html
上一篇: 如何为Eclipse添加FTP支持?