Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google.Protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero)

I have a problem with my school project, i use Protobuf library but i have the following error:

Google.Protobuf.InvalidProtocolBufferException" Protocol message contained an invalid tag (zero).

My protocol message wrapper is:

syntax = "proto3";
package CardGameGUI.Network.Protocol.Message;

message WrapperMessage {
enum MessageType {
    HELLO_MESSAGE = 0;
    JOIN_ROOM_MESSAGE = 1;
    JOIN_ROOM_RESPONSE_MESSAGE = 2;
}

MessageType type = 1;
bytes       payload = 2;
}

I use this to send a message:

    public void SendObject<T>(Protocol.Message.WrapperMessage.Types.MessageType type, T messageObject)
    {
        byte[] message;

        // Serialize message
        using (var stream = new MemoryStream())
        {
            ((IMessage)messageObject).WriteTo(stream);

            message = stream.GetBuffer();
        }

        byte[] wrapper = new Protocol.Message.WrapperMessage{Type = type, Payload = Google.Protobuf.ByteString.CopyFrom(message)}.ToByteArray();

        Connection.SendObject<byte[]>("ByteMessage", wrapper);
    }

And my server handler:

private void IncommingMessageHandler(PacketHeader header, Connection connection, byte[] message)
    {
        Protocol.Message.WrapperMessage wrapper = Protocol.Message.WrapperMessage.Parser.ParseFrom(message);

        switch (wrapper.Type)
        {
            case Protocol.Message.WrapperMessage.Types.MessageType.HelloMessage:
                GetClient(connection.ConnectionInfo.NetworkIdentifier).MessageHandler(Protocol.Message.HelloMessage.Parser.ParseFrom(wrapper.Payload.ToByteArray()));

                break;
        }
    }

The wrapper message is perfectly unserialized, and type is correctly matched, but at the treatment of my Payload, the exception pops.

Do i do something bad?

Edit: a small screen of the message Payload Payload

like image 937
Jean Walrave Avatar asked Nov 09 '17 04:11

Jean Walrave


1 Answers

The problem is probably that you used GetBuffer without making use of the known length. GetBuffer returns the oversized backing array. The data after the stream's .Length is garbage and should not be consumed - it will typically (but not always) be zeros, which is what you are seeing.

Either use ToArray() instead of GetBuffer(), or track the .Length of the stream and only consume that much of the oversized buffer.


Another possibility is "framing" - it looks like you're handling packets, but if this is TCP there is no guarantee that the chunks you receive are the same sizes as the chunks you send. If you are sending multiple messages over TCP you need to implement your own framing (typically via a length prefix, since you're talking binary data).


Incidentally, this isn't protobuf-net.


If neither of those is the problem: check the data you receive is exactly (byte for byte) the data you send (including lengths). It is easy for data to get corrupted or mis-chunked by IO code.

like image 159
Marc Gravell Avatar answered Nov 14 '22 19:11

Marc Gravell