Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem deserializing data with protobuf-net that was serialzed by google's protobuf

I am currently working on code that serializes in one app (C++) and needs to deserialize it in another (C#). I am trying to use google proto + protobuf-net but something is failing.

Both the .cc and the .cs message definition files were generated with their respective compilers, from the same .proto file.

The data is being sent via UDP, and the messages (~40B) easily fit into a single datagram.

On the C++ size, boost::asio is being used to transmit the data, the relevant code being:

ProtocolBufferdata data;
...
boost::asio::streambuf b;
std::ostream os(&b);
data.SerializeToOstream(&os);
m_Socket.send_to(b.data(), m_Endpoint);

I am fairly sure this is working correctly, since using wireshark I can at least see all the strings I expect in the datagram. On the C# side, using Begin/End recieve, we have the following in the callback:

byte[] buffer ....        

public void ReceiveData(IAsyncResult iar)
{
    try
    {
        Socket remote = (Socket)iar.AsyncState;
        int recv = remote.EndReceive(iar);
        using (MemoryStream memStream = new MemoryStream())
        {
            memStream.Write(buffer, 0, recv);
            ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData >(memStream);
            onReceive(data);
        }
    }
    catch (Exception ex)
    {
        ...
    }
    finally
    {
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), socket);
    }
}

The buffer does have the expected number of bytes in it, and has the tell-tale strings. The protobuf-net container has all default values.

I am a bit puzzled about what is going on here, and it is almost impossible to attach a debugger to the client application since it is deployed as a plug-in to another application that does not play well with a remote debugger. I would appreciate any advice, this has me stumped.

like image 445
Chuu Avatar asked Jan 27 '11 07:01

Chuu


1 Answers

Rewind your stream - it is at the end, so Read will return no data:

memStream.Write(buffer, 0, recv);
memStream.Position = 0; // <===========here
ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData>(memStream);

alternatively, use the overloaded constructor to prepare the stream:

using (MemoryStream memStream = new MemoryStream(buffer, 0, recv))
{
    ProtoData data = ProtoBuf.Serializer.Deserialize<ProtoData>(memStream);
like image 57
Marc Gravell Avatar answered Oct 03 '22 15:10

Marc Gravell