【问题标题】:Parsing a protocol message from Go by Java通过 Java 解析来自 Go 的协议消息
【发布时间】:2017-07-25 18:01:08
【问题描述】:

我编写了一个服务器(Go)-客户端(Java)程序,并使用 protobuf 进行通信。 定义一个 proto 文件并在服务器和客户端之间共享。 在服务器端:

  • 将共享的proto文件编译成go by protoc
  • 通过proto.Marshal序列化对象
  • 将其发送给对其服务提出请求的客户端

在客户端:

  • 通过protoc将共享的proto文件编译成java
  • 获取字节通过http传输
  • 将字节反序列化为对象。

这里出现以下错误:

“com.google.protobuf.InvalidProtocolBufferException:在解析协议消息时,输入意外在字段中间结束。这可能意味着输入已被截断,或者嵌入的消息误报了自己的长度。”

我确认 http 工作正常,客户端接收到的字节值与服务器发送的字节值相同。你有同样的问题吗?

这是原型文件

syntax = "proto3";
package tutorial;

message Person {
    string name = 1;
    int32 id = 2; 
    string email = 3;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
    }

    repeated PhoneNumber phones = 4;
}

message AddressBook {
    repeated Person people = 1;
}

在 Go 服务器端:

func TodoIndex(w http.ResponseWriter, r *http.Request) {

    w.Header().Set("Content-Type", "application/x-protobuf")
    w.WriteHeader(http.StatusOK)
    p := &Person{
        Id:    1234,
        Name:  "John Doe",
        Email: "jdoe@example.com",
        Phones: []*Person_PhoneNumber{
            {Number: "555-4321", Type: Person_HOME},
        },
    }
    out, err := proto.Marshal(p)
    if err != nil {
        panic(err)
    }
    w.Write(out)
}

在Java客户端:

public class MainJavaAndGo {
public static void main(String[] args){
    try {
        long start = (new Date()).getTime();
        System.out.println("begin get");
        connect();

        System.out.println("end get");
        long time = (new Date()).getTime() - start;
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void connect(){
    DefaultBHttpClientConnection connection = new DefaultBHttpClientConnection(8 * 1024);
    HttpHost server = hostForString("localhost:8080");
    try {

        Socket socket = new Socket(server.getHostName(), server.getPort());
        connection.bind(socket);

        HttpCoreContext writeContext = HttpCoreContext.create();
        writeContext.setTargetHost(server);

        BasicHttpEntityEnclosingRequest httpRequest = new BasicHttpEntityEnclosingRequest("GET",
                "/todos");

        HttpProcessor httpproc = makeHttpProcessor();
        HttpRequestExecutor httpexecutor = new HttpRequestExecutor();
        httpexecutor.preProcess(httpRequest, httpproc, writeContext);
        HttpResponse response = httpexecutor.execute(httpRequest, connection, writeContext);
        httpexecutor.postProcess(response, httpproc, writeContext);
        InputStream inputStream = response.getEntity().getContent();
        byte[] data = IOUtils.toByteArray(inputStream);
        Addressbook.AddressBook addressBook = Addressbook.AddressBook.parseFrom(data);
        int foo = 0;
        foo++;


    }catch(Exception e){
        e.printStackTrace();
        try {
            connection.shutdown();
        }catch (Exception ioe){
            ioe.printStackTrace();
        }
    }
}
public static  HttpHost hostForString(String hostStr) {
    String[] host = hostStr.split(":", 2);
    HttpHost httphost = new HttpHost(host[0], Integer.parseInt(host[1]));

    return httphost;
}

public static HttpProcessor makeHttpProcessor() {
    return HttpProcessorBuilder.create().add(new RequestContent()).add(new RequestTargetHost())
            .add(new RequestConnControl()).add(new RequestUserAgent("Test Protobuf/1.1"))
            .add(new RequestExpectContinue(true)).build();
}
}

我得到了 InvalidProtocolBufferException

com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either that the input has been truncated or that an embedded message misreported its own length.
    at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:82)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.skipRawBytes(CodedInputStream.java:1200)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.skipField(CodedInputStream.java:578)
    at com.auth0.protobuf.Addressbook$Person.<init>(Addressbook.java:112)
    at com.auth0.protobuf.Addressbook$Person.<init>(Addressbook.java:77)
    at com.auth0.protobuf.Addressbook$Person$1.parsePartialFrom(Addressbook.java:1817)
    at com.auth0.protobuf.Addressbook$Person$1.parsePartialFrom(Addressbook.java:1812)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.readMessage(CodedInputStream.java:816)
    at com.auth0.protobuf.Addressbook$AddressBook.<init>(Addressbook.java:1914)
    at com.auth0.protobuf.Addressbook$AddressBook.<init>(Addressbook.java:1871)
    at com.auth0.protobuf.Addressbook$AddressBook$1.parsePartialFrom(Addressbook.java:2571)
    at com.auth0.protobuf.Addressbook$AddressBook$1.parsePartialFrom(Addressbook.java:2566)
    at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:163)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:197)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:209)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:214)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
    at com.auth0.protobuf.Addressbook$AddressBook.parseFrom(Addressbook.java:2065)
    at com.auth0.MainJavaAndGo.connect(MainJavaAndGo.java:78)
    at com.auth0.MainJavaAndGo.main(MainJavaAndGo.java:35)

【问题讨论】:

  • Java 端的套接字是什么样的?听起来您只收到了部分消息。
  • 在Java端,我通过HttpRequestExecutor请求服务 HttpHost server = new HttpHost("localhost", 8080); Socket socket = new Socket(server.getHostName(), server.getPort()); connection.bind(socket);
  • 你在什么时候从套接字读取?你能用它来编辑你的原始帖子,使其格式正确吗?
  • 感谢您的评论。我刚刚发布了完整版的 java 客户端,我通过 httpexecutor.execute 通过 HttpResponse 从服务器获取字节。这就像对宁静服务的请求的响应。

标签: java go protocol-buffers


【解决方案1】:

谢谢大家 我从你的所有评论中找到了答案。 我的序列化和反序列化结构不同。 我编辑为 Addressbook.Person person = Addressbook.Person.parseFrom(data); 然后它就起作用了。

【讨论】:

    猜你喜欢
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 2022-10-14
    • 1970-01-01
    相关资源
    最近更新 更多