尝试在 java 中使用 protobuf 发送和接收消息,但出现错误:协议消息包含无效标签(零)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14272852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:42:43  来源:igfitidea点击:

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

javaprotocol-buffers

提问by Ryan Zhu

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

问题发生在服务器端, parseDelimitedFrom() 调用。

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:

原来服务器端会在 parseFrom() 再次调用时中断。但是当我评论两行时:

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?

在客户端, parseFrom() 调用刚刚工作没有问题。一开始我怀疑.proto文件有问题,后来证明没有问题……那么这个问题是怎么来的呢?是因为我在 parseFrom() 调用之前错过了一些数据吗?

采纳答案by Jon Skeet

I can't remember exactly what format parseDelimitedFromexpects, but I suspectyou just want parseFromin your server side.

我不记得确切的格式parseDelimitedFrom需要什么,但我怀疑你只是想parseFrom在你的服务器端。

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 OutputStreamand InputStream, writing:

目前尚不清楚您为什么要使用os.write(request.toByteArray()),或者您为什么要创建DataOutputStream. 你应该能够使用 just OutputStreamand InputStream,写作:

request.writeTo(socket.getOutputStream());

and then:

接着:

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

If you dowant the delimited version, you need to use writeDelimitedToinstead.

如果您确实需要分隔版本,则需要writeDelimitedTo改用。