2016-06-28 66 views
1

對於這兩種Protobufs我都有一個很大的問題。在C++上使用Protobuf-net與C#(UDP)聊天的Googles ProtoBuf

我在C++上使用Google的Protobuf服務器/客戶端應用程序。 它工作得很好。

客戶端將數據發送到服務器,該服務器應將此消息 分發給其他客戶端。

C++客戶端是一個純粹的發送者,將Protobuf-Struct封裝在固定大小(500個大氣壓)的Char數組中。

C++ Server將其反序列化,查找命令(登錄註銷或其他消息)以及(如果其消息)將其發送給C#-Client。 這也是由500個字符的固定大小完成的。

這工作得很好。 現在在C#端:

C#客戶端atm可以登錄並使用Protobuf-net發送消息。即使Protobuf-Net將其打包爲一個字節數組(與C++中的char數組不同的是,它與C++中的char數組不同,它的大小也是一樣)。 即使如此,服務器也會識別該消息並將其打印出來。

但是(這裏是令人毛骨悚然的問題),當服務器轉發來自c + +的消息 - 客戶端我在C#中遇到很大的問題。

注意:客戶端在Unity3D中實現。

Unity收到Byte-Array幾乎沒問題。 需要注意的一點是,字節數組是無符號的,與服務器發送的消息不同。這導致-1成爲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(); 
} 

這是C#的客戶端。

C++ - 代碼:

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

這是C++ - 客戶端

的C++ - 服務器只轉發該炭數組到C#-client, 是一樣的UDP-沒有序列化部分的客戶端。

我得到的錯誤,如: ProtoException:在源數據 無效的字段:0

或Invalide線型

編輯: 這是原癌文件

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#我使用-Net編譯器來創建CS文件 然後從它構建庫文件,參考ProtoBuf.dll爲了統一 ,然後讓預編譯器將Serialize.dll包含在Unity3D中

+0

實際上你的問題是什麼? –

+0

已更新。問題是:爲什麼我得到這些錯誤。爲什麼不行? :/ –

回答

0

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

如果傳入消息的長度固定(在我的情況下爲500),如果Protobuf的長度不是Protobuf的確切字節大小,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(); 
} 
0

好的,我更好地重讀了你的代碼。我認爲這個問題可能與你處理C#服務器的方式有關。我認爲你應該嘗試這種方法:

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

+0

這給了我:InvalidCastException:不能從源類型轉換爲目標類型。SendPackSerializer.Deserialize(Int32,System.Object,ProtoBuf.ProtoReader) –

+0

這聽起來像是一個演員錯誤(我可能弄亂了變量),檢查Derialize的簽名並相應地修復這些變量。 – Robbykk

+0

已經找到解決方案。如果任何人可能有相同的問題,請將其張貼在此主題中 –