2016-06-28 20 views
1

Ich habe ein großes Problem in Bezug auf diese beiden Protobufs.Googles ProtoBuf auf C++ Chats mit Protobuf-net auf C# (UDP)

Ich habe eine Server/Client-Anwendung auf C++ mit Googles Protobuf. Es funktioniert ganz gut.

Der Client sendet die Daten an den Server, der diese Nachricht an die anderen Clients verteilen soll.

Der C++ - Client ist ein reiner Absender und packt das Protobuf-Struct in einem Char-Array mit fester Größe (500 atm).

Der C++ Server deserialisiert es, sucht nach dem Befehl (Login Logout oder eine Nachricht an andere) und sendet es (wenn es eine Nachricht ist) an den C# -Client. Dies geschieht auch mit einer festen Größe von 500 Zeichen.

Das funktioniert ganz gut. Jetzt auf der C# -Seite:

Der C# -Client ATM kann sich anmelden und Nachrichten mit Protobuf-Net senden. Das funktioniert ziemlich genial, obwohl Protobuf-Net es in einem Byte-Array (das im Gegensatz zum Char-Array auf C++ - Seite nicht signiert ist) mit dyana- mischer Größe packt. Trotzdem erkennt der Server die Nachricht und druckt sie aus.

ABER (und hier ist das Freaking Problem), wenn der Server eine Nachricht vom C++ - Client weiterleitet bekomme ich große Probleme in C#.

Für den Hinweis: Der Client ist in Unity3D implementiert.

Unity empfängt das Byte-Array fast in Ordnung. Eine Sache zu beachten ist, dass das Byte-Array im Gegensatz zu der Nachricht, die vom Server gesendet wird, unsigniert ist. Dies führt zu -1 255

C# -Code werden:

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

Dies ist das C#-Client.

C++ - Code:

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

Dies ist die C++ - Client-

Die C++ - Server leitet nur den char-Array mit dem C# -Client, , die die gleiche wie die UDP- ist Client ohne den Serialisierungsteil.

I Get Fehler wie: ProtoException: Ungültige Feld in Quelldaten: 0

oder Invalide Draht-Typ

edit: Dies ist die Proto-Datei

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

Für C++ Ich benutze den normalen Proto-Compiler Für C# verwende ich -Netz-Compiler, um eine CS-Datei dann erstellen Sie Bibliothek daraus, mit Bezug auf ProtoBuf.dll für Einheit und dann lassen Sie den Precompiler eine Serialize.dll machen in Unity3D

+0

Was ist Ihre Frage eigentlich? –

+0

aktualisiert. Frage ist: Warum bekomme ich diese Fehler. Warum funktioniert es nicht? :/ –

Antwort

0

Alles in Ordnung. Ich habe jetzt die Antwort gefunden.

Protobuf-Net hat echte Probleme, wenn die eingehende Nachricht eine feste Länge (in meinem Fall 500) hat, wenn es nicht die genaue Byte-Größe des Protobuf ist.

I geändert meine C++ - Server auf diese Weise:

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

Und dann mit dieser Größe senden Sie es.

Wie ich in meinem OP erwähnt habe, kann die C++ - Version Nachrichten behandeln, die in Arrays fester Größe gepackt sind und sie entschlüsseln.

Jetzt auf dem C# -Part muss ich ein wenig arbeiten.

Ich erhalte immer noch eine Nachricht und lege sie in ein Byte-Array fester Größe. Wenn ich nur ein nicht initialisiertes Array verwende, bekomme ich Fehler.

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

Ok, ich lesen Sie Ihren Code besser. Ich denke, dass das Problem auf die Art und Weise, wie Sie den C# -Server behandeln, hängt.Ich denke, dass Sie diesen Ansatz versuchen sollten:

MemoryStream Stream = neue MemoryStream (eingehende, falsche);
ModelSerializer Serialisierung = new ModelSerializer(); Nachricht = (SendPack) Serializer.Deserialize (Strom, eingehende, typeof (eingehende));

+0

Das gibt mir: InvalidCastException: kann nicht von Quellentyp zu Zieltyp umwandeln. SendPackSerializer.Deserialize (Int32, System.Object, ProtoBuf.ProtoReader) –

+0

Es klingt wie ein Cast-Fehler (ich habe die Variablen möglicherweise versaut), überprüfen Sie die Signatur von Derialize und beheben Sie die Variablen entsprechend. – Robbykk

+0

Bereits eine Lösung gefunden. Hat es in diesem Thread gepostet, wenn jemand das gleiche Problem haben könnte –