2016-05-23 1 views
1

Ich versuche, eine Nachricht in C++ mit Google Proto zu serialisieren, es über einen TCP-Socket zu senden und schließlich in einem C# -Client zu empfangen und zu analysieren.SkipLastField hat ein Endgruppen-Tag aufgerufen. GoogleProtobuf (C# und C++)

Ich halte die folgende Ausnahme auf den Parser C# google proto bekommen:

auf einer Ende-Gruppen-Tag genannt SkipLastField anzeigt, dass die entsprechende Start-Gruppe

ich das gedruckte fehlte Serialisierter Eingangsstrom, sowohl vor dem Senden als auch nach dem Empfang, und er passt perfekt an beide Enden.

C# Listener/Deserializer

namespace NetStreamHandler 
{ 
    public class Server 
    { 
     public static void ReceiveData() 
     { 
      var ipAddress = IPAddress.Parse("127.0.0.1"); 
      var listener = new TcpListener(ipAddress, 20511); 
      listener.Start(); 
      listener.BeginAcceptSocket(MessageReceived, listener); 
     } 

     private static void MessageReceived(IAsyncResult result) 
     { 
      var server = (TcpListener)result.AsyncState; 
      using (var client = server.EndAcceptTcpClient(result)) 
      using (var stream = client.GetStream()) 
      { 
       try 
       { 
        var cod = new CodedInputStream(stream); 
        var packet = Serialize.Parser.ParseFrom(cod); 
        Console.WriteLine($"Message: {packet.ToString()}"); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine($"Exception Caught at: {ex.Message}\n"); 
       } 
      } 
     } 

    } 
} 

C++ senden/Serialize

int bCount; 
Serialized::Serialize pLoad; 
pLoad.set_command("Test"); 
pLoad.set_id(10); 
pLoad.set_num(3); 
pLoad.set_packettype(1); 
pLoad.set_ret("Test"); 

printf("Size after serializing: %d bytes\n", pLoad.ByteSize()); 
auto size = pLoad.ByteSize(); 
auto packet = new char[size]; 
ArrayOutputStream ArrayOut(packet, size); 
auto coutput = new CodedOutputStream(&ArrayOut); 
coutput->WriteVarint32(pLoad.ByteSize()); 
pLoad.SerializeToCodedStream(coutput); 
auto sConnect = SetupSocket(); 
if (!sConnect) { printf("Socket failure\n"); goto DONE; } 
std::cout << "Buffer:" << byte_2_str(packet, size) << std::endl; 


bCount = send(sConnect, packet, size, 0); 
if(bCount == SOCKET_ERROR) 
{ 
    fprintf(stderr, "Server: send() failed: error %d: %s\n", WSAGetLastError(), DecodeError(WSAGetLastError())); 
    goto DONE; 
} 
else if (bCount == -1) { 
    fprintf(stderr, "Error sending data %d\n", errno); 
    goto DONE; 

} 
else { 
    printf("Sent bytes %d\n", bCount); 
} 

DONE: 
closesocket(sConnect); 
printf("All done..\n"); 
+0

Haben Sie alle die Nachricht empfangen, bevor Sie das Parsen starten Sie den Server senden kann? 8000 Bytes, aber es gibt keine Garantie in TCP, dass es in einem Paket empfangen wird, z. B. könnte es als zwei 4000-Byte-Pakete empfangen werden. 'stream.Read (...)' würde 4000 Bytes lesen & 4000 zurückgeben, dann erneut aufgerufen, 4000, und dann beim letzten Aufruf 0 zurückgeben, um anzuzeigen, dass keine Daten mehr zu lesen sind. –

Antwort

1

Sie nur in der ArrayOut verwendet Nutzlastgröße Bytes für den Puffer zugeordnet sind, die an den CodedOutputStream gebunden ist. Aber Sie haben versucht, etwas mehr (Payload-Größe + Größe (Varint32) zu schreiben Raten Sie Puffer haben, müssen groß genug Nutzlast speichern mit Nachrichtenlänge

I Poco Framework verwenden Hier ist C++ Beispielcode unter:...

.
void writeDelimitedTo(const google::protobuf::MessageLite& message, Poco::Net::StreamSocket& socket) { 
    int totalMsgSize = message.ByteSize()+4; // Variant32 length 1-4 
    char *buf = new char [totalMsgSize]; 
    ArrayOutputStream aos(buf, totalMsgSize); 
    CodedOutputStream coded_output(&aos); 
    coded_output.WriteVarint32(message.ByteSize()); 
    message.SerializeToCodedStream(&coded_output); 
    socket.sendBytes(buf, coded_output.ByteCount()); 
    delete buf; 
} 

und natürlich C# Teil mit System.Io.Stream wie clientStream ProtoMsgStructRequest und ProtoMsgStructResponse sind protobuf Nachrichten:

using (var pbReader = new Google.Protobuf.CodedInputStream(clientStream, true)) 
{ 
    var inRequest = new ProtoMsgStructRequest(); 
    pbReader.ReadMessage(inRequest); 
    { 
     var outResponse = new ProtoMsgStructResponse(); 
     using (var pbWriter = new Google.Protobuf.CodedOutputStream(clientStream, true)) 
     { 
      pbWriter.WriteMessage(outResponse); 
     } 
    } 
}