Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to send and receive message using protobuf in java,but got error: Protocol message contained an invalid tag (zero)

The problem happened at server end, parseDelimitedFrom() calling.

Client End:

    C2SGainCard.Builder s = C2SGainCard.newBuilder();
    C2SGainCard c2s = s.build();

    GameRequest.Builder  reqBuilder=GameRequest.newBuilder();
    reqBuilder.setBody(c2s.toByteString());
    reqBuilder.setName(C2SGainCard.class.getSimpleName());
    reqBuilder.setPlayerId("3");
    GameRequest request=reqBuilder.build();

    DataOutputStream os = new DataOutputStream(socket.getOutputStream());
    os.write(request.toByteArray());
    os.flush();
    os.close();
    socket.close();

Server End:

    try{
        DataInputStream is = new DataInputStream(socket.getInputStream());
        GameRequest gameRequest = GameRequest.parseDelimitedFrom(is);
    }catch(Exception ex){
        System.out.println(ex.getMessage());
    }

And here is the another similar question:

Client End:

    C2SSell.Builder s = C2SSell.newBuilder();
    CardOnSell.Builder cardOnSell = CardOnSell.newBuilder();
    cardOnSell.setId(1);
    cardOnSell.setPlayerId(3);
    cardOnSell.setCardId(1);
    cardOnSell.setCurrentPrice(111);
    cardOnSell.setFixedPrice(555);
    cardOnSell.setDescription("cao");

    s.setCardOnSell(cardOnSell.build());

    C2SSell c2s = s.build(); 

socket processing was the same.

Server End:

    DataInputStream is = new DataInputStream(socket.getInputStream());
    byte[] b = new byte[1024];
    int len=is.read(b);
    String as = new String(b, 0, len);
    GameRequest gameRequest=GameRequest.parseFrom(as.getBytes());

Turns out that the server end will break at the parseFrom() calling again.But when I comment two lines:

cardOnSell.setCurrentPrice(111);
cardOnSell.setFixedPrice(555);

on the client End,the parseFrom() calling just worked without problem. At frist I suspected the .proto file has some problems and it's been proved there is no problem there... So how does this problem come? It that because I miss some data before the parseFrom() calling?

like image 558
Ryan Zhu Avatar asked Jan 11 '13 06:01

Ryan Zhu


People also ask

Is protobuf a communication protocol?

Protocol Buffers (Protobuf) is a free and open-source cross-platform data format used to serialize structured data. It is useful in developing programs to communicate with each other over a network or for storing data.

What is Google protobuf empty?

protobuf. Empty states: A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method.

Does protobuf use HTTP?

Protobufs work fine over HTTP in their native binary format.

What is the protobuf wire format?

Protocol Buffers is a high-performance, compact binary wire format invented by Google who use it internally so they can communicate with their internal network services at very high speed.


1 Answers

I can't remember exactly what format parseDelimitedFrom expects, but I suspect you just want parseFrom in your server side.

It's not clear why you're using os.write(request.toByteArray()) though, or indeed why you're creating a DataOutputStream. You should be able to use just OutputStream and InputStream, writing:

request.writeTo(socket.getOutputStream());

and then:

GameRequest gameRequest = GameRequest.parseFrom(socket.getInputStream());

If you do want the delimited version, you need to use writeDelimitedTo instead.

like image 113
Jon Skeet Avatar answered Oct 16 '22 17:10

Jon Skeet