当前位置: 首页 > 知识库问答 >
问题:

解析Go by Java的协议消息

景永春
2023-03-14

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

  • 将共享的proto文件编译为go by Protoc
  • 按proto.marshal序列化对象
  • 将其发送给对其服务提出请求的客户端

在客户端:

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

这里有以下错误:

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

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

这是proto文件

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)

共有1个答案

卫寒
2023-03-14

谢谢。我从你的评论中找到了答案。我的序列化和反序列化结构是不同的。我编辑到AddressBook.person person=AddressBook.person.ParseFrom(数据);然后起作用了。

 类似资料:
  • 消息协议 节点之间通过消息来进行交互,所有消息都由下面的数据结构来实现。 message Message { enum Type { UNDEFINED = 0; DISC_HELLO = 1; DISC_DISCONNECT = 2; DISC_GET_PEERS = 3; DISC_PEERS = 4;

  • 本文根据 SOFAChannel#13 直播分享整理,主题:云原生网络代理 MOSN 多协议机制解析。 本文根据 SOFAChannel#13 直播分享整理,主题:云原生网络代理 MOSN 多协议机制解析,查看视频回顾。 作者:无钩,目前主要从事蚂蚁集团网络代理相关的研发工作,也是 MOSN 的 Committer。 今天我要和大家分享的是《云原生网络代理 MOSN 多协议机制解析》,并介绍对应的

  • 本文主要是对 MOSN 多协议机制解析,并介绍对应的私有协议快速接入实践案例以及对 MOSN 实现多协议低成本接入的设计进行解读。 我们将按以下顺序进行介绍: 多协议机制产生的背景与实践痛点; 常见的协议扩展思路初探; SOFABolt 协议接入实践; MOSN 多协议机制设计解读; 后续规划及展望; 其中第三点「接入实践」是今天分享的重点,希望能给大家就「如何在 MOSN 中快速扩展私有协议接入

  • 在阅读这个相当长的问题之前,我提出了一个bughttps://github.com/GoogleCloudPlatform/python-docs-samples/issues/1103. 原型包和名称解析的留档状态 您可以使用其他定义。通过导入原始文件。导入另一个。在proto的定义中,您可以在文件的顶部添加一条import语句。 我的依赖于annotations.proto将HTTP/JSON

  • 物联网核心在人、机、云之间的信息互联,因此智能设备、云端、手机端会通过各种协议进行数据的交换,包括网络、蓝牙、USB、 ZigBee 等种种通信协议,实现万物互联的效果,因此在物联网安全分析中,对其中的通信协议的分析是关键的一环,本节将对常见的通信协议进行分析。

  • 本文向大家介绍深入解析Swift语言中的协议,包括了深入解析Swift语言中的协议的使用技巧和注意事项,需要的朋友参考一下 协议为方法,属性和其他要求的功能提供了一个蓝本。它只是描述了方法或属性的骨架,而不是实现。方法和属性实现还可以通过定义类,函数和枚举完成。协议的一致性是指方法或属性满足协议的要求。 语法 协议也遵循类似类,结构和枚举的语法: 协议在类,结构或枚举类型命名声明。单个和多个协议的