1

Are there any special requirements, when using Protobuf-net to send a binary array? I have a message class, that wraps some binary data:

[ProtoContract]
public class BitmapPackage : BaseMessage
{
    [ProtoMember(1)]
    public byte[] BitmapData;
}

When trying to deserialize the message I catch the exception thrown by the Protobuf-net:

16:52:59.902: (007): [Error] Inner Exception in StartReceiveLoop():Message: Attempted to read past the end of the stream.Stack Trace: at ProtoBuf.ProtoReader.Ensure(Int32 count, Boolean strict) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 257 at ProtoBuf.ProtoReader.AppendBytes(Byte[] value, ProtoReader reader) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 921 at proto_4(Object , ProtoReader ) at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line 57 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 775 at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 700 at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 588 at ProtoBuf.Serializer.Deserialize[T](Stream source) in c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 77

This happens only and always when I send one specific bitmap. So my question is should I somehow "escape" the binary data before deserializing it using protobuf-net?

UPDATE: Here is the code that is doing the receiving:

private async Task StartReceiveLoop()
{
await Task.Yield();

while(!_readOpCancelToken.IsCancellationRequested)
{
    try
    {
        var buffer = new byte[4096];
        int bytesRx = await _pipe.ReadAsync(
            buffer, 0, buffer.Length, _readOpCancelToken);

        Logger.LogInfo("Pipe connection: Got " + bytesRx + " bytes");

        if (bytesRx == 0) break;
        if (_readOpCancelToken.IsCancellationRequested) break;

        await _receivedDataStream.WriteAsync(buffer, 0, bytesRx);

        if (_pipe.IsMessageComplete)
        {
            // Get out the routing data
            _receivedDataStream.Position = 0;
            byte[] intbuffer = new byte[4];

            _receivedDataStream.Read(intbuffer, 0, 4);
            int size = BitConverter.ToInt32(intbuffer, 0);

            _receivedDataStream.Read(intbuffer, 0, 4);
            int typeId = BitConverter.ToInt32(intbuffer, 0);

            _receivedDataStream.Read(intbuffer, 0, 4);
            int routeTag = BitConverter.ToInt32(intbuffer, 0);

            messageObj = messageObj = Serializer.NonGeneric.Deserialize(messageType, _receivedDataStream);

            // Process message on UI thread via tick queue
            TickSystem.OneTimeTickQueue.Enqueue(new Action(() =>
            {
                ProcessMessageExtApp.ProcessThisMessage(messageObj);
            }));

            // Reset the stream
            _receivedDataStream = new MemoryStream();
        }
    }
    catch (Exception e)
    {
        Logger.LogError(
            "Exception in StartReceiveLoop():" +
            "Message: " + e.Message +
            "Stack Trace: " + e.StackTrace);

        if (e.InnerException != null)
        {
            Logger.LogError(
            "Inner Exception in StartReceiveLoop():" +
            "Message: " + e.InnerException.Message +
            "Stack Trace: " + e.InnerException.StackTrace);
        }
    }
}

}

2
  • Your receive logic is broken, this is not protofuf's fault. You are passing incomplete data. Not sure what you mean by escaping. Post the code that is responsible for handing data to protobuf. Probably you should fix your logging as well because error details seems to be missing. It's best to log the full exception ToString. Commented Jul 1, 2015 at 15:04
  • Looks good. What about exceptions? The handling broken because you will continue the loop forever in case of an error. Post the sending code as well because I can't spot a problem with the reading code. Commented Jul 1, 2015 at 15:24

1 Answer 1

1

The actual problem was not the Protobuf-net, but a fact, that IsMessageComplete was signaled prematurely. The fix was to write to the Pipe on the pipe server using a byte array instead stream copy and flush the pipe after finishing each packet.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.