2

我有这样的 protobuf 消息:

message Update {
  Path path = 1;                      // The path (key) for the update.
  Value value = 2 [deprecated=true];  // The value (value) for the update.
  TypedValue val = 3;                 // The explicitly typed update value.
}

// TypedValue is used to encode a value being sent between the client and
// target (originated by either entity).

message TypedValue {
    oneof value {
        string string_val = 1;            // String value.
        int64 int_val = 2;                // Integer 
        ....
        google.protobuf.Any any_val = 9;  // protobuf.Any encoded bytes.
        ....
  }
}

在服务器端(C++),我们将这个字段设置如下(LLDP 是外部类,Interfaces 在里面):

   openconfig_lldp::Lldp out;
   GetLldpProto(&out);

   update->mutable_val()->mutable_any_val()->PackFrom(out.interfaces());

在客户端(Java)上,我们像这样提取这个字段:

OpenconfigLldp.Lldp.Interfaces interfaces = update.getVal().getAnyVal().unpack(OpenconfigLldp.Lldp.Interfaces.class);

这会引发 InvalidProtocolBufferException 异常。当我在我的 Java 客户端中转储“更新”时,我看到:

path {
  elem {
    name: "lldp"
  }
  elem {
    name: "interfaces"
  }
}
val {
  any_val {
    type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"
    value: "\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/1\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/2\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/3\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n\212\207\237\334\v\374\001\022\371\001\262\211\267l\031\342\367\304\260\002\v\n\tEth 1/1/4\242\340\247\230\017\002\b\001\352\316\234\250\017\324\001\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh1\342\253\214\353\001\v\n\tEth 1/1/1\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh2\342\253\214\353\001\v\n\tEth 1/1/2\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh3\342\253\214\353\001\v\n\tEth 1/1/3\242\364\301\261\a\002\b\n\262\217\304\272\017/\022-\302\340\317\247\001\'\202\225\377\302\001\b\n\006Neigh4\342\253\214\353\001\v\n\tEth 1/1/4\242\364\301\261\a\002\b\n"
  }
}

type_url 对我来说似乎是正确的。我在这里做错了什么?

谢谢你的时间。

编辑#1:

我查看了异常字符串。它是“Any 消息的类型与给定的类不匹配”。

C++ 和 Java 使用相同的 proto 文件,但我在 C++ 中看到“openconfig_lldp.Lldp.Interfaces”,而在 Java 中它是“OpenconfigLldp.Lldp.Interfaces”。需要找出原因。。

编辑#2:

使用相同的 .proto 文件。在这种情况下,它是:

openconfig_lldp.proto
---------------------
syntax = "proto3";

package openconfig.openconfig_lldp;

message Lldp {
    message Config {
        ....
        ....
    }
    ....
    ....
}

对于 Java,我在名为 openconfig_lldp 的包中看到父类为 OpenconfigLldp。

package openconfig.openconfig_lldp;

public final class OpenconfigLldp {
  private OpenconfigLldp() {}
  ....
  ....
  /**
   * Protobuf type {@code openconfig.openconfig_lldp.Lldp}
   */
  public  static final class Lldp extends com.google.protobuf.GeneratedMessageV3 implements
    // @@protoc_insertion_point(message_implements:openconfig.openconfig_lldp.Lldp)
   ....
   ....
}

在 C++ 中,我没有看到任何名为“OpenconfigLldp”的类生成。相反,它只是“Lldp”

所以,Any.protobuf 中的 type_url 是不匹配的。C ++方面将其作为

type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"

在 Java 端,我使用:

OpenconfigLldp.Lldp.Interfaces interfaces = update.getVal().getAnyVal().unpack(OpenconfigLldp.Lldp.Interfaces.class);

任何人都想过为什么在 Java 协议输出中有一个包装类?

编辑#3

显然看起来是因为“outer_class_name”。在 Java 代码中,我有一个外部类“OpenconfigLldp”。

type_url 格式为:

type.googleapis.com/packagename.messagename

因此,C++ 代码将其设置为 openconfig_lldp.Lldp.Interfaces。但是,这映射到 Java 中的 OpenconfigLldp.Lldp.Interfaces。

我该如何解决这个问题?

最后的编辑和最后的问题

经过一番挖掘,这就是我发现的。默认情况下,type_url 是:

type_url: "type.googleapis.com/openconfig_lldp.Lldp.Interfaces"

在 Java 方面,我查看了 Any 实现。它试图将其与以下内容进行比较:

openconfig.openconfig_lldp.Lldp.Interfaces 

我通过打印发现了这一点:

Lldp.Interfaces defaultInstance = (Lldp.Interfaces)Internal.getDefaultInstance(Lldp.Interfaces.class);
logger.info("full descriptor name: " + defaultInstance.getDescriptorForType().getFullName());

所以,我破解了 C++ 端发送:

update->mutable_val()->mutable_any_val()->set_type_url(std::string("type.googleapis.com/openconfig.openconfig_lldp.Lldp.Interfaces"));

所以,我想我知道这里发生了什么!

感谢您阅读所有编辑。

4

1 回答 1

0

我不确定我是否正确理解出了什么问题——理想情况下,限定名称将位于协议缓冲区命名空间中——特定于语言的映射无关紧要。

如果问题仍然悬而未决,我建议将其核心移到顶部,将编辑保留为“我到目前为止所做的”。

也许这是可以解决这些选项的某种错误:

  • java_multiple_files
  • java_outer_classname

可以在此处找到有关这些选项的更多详细信息: https ://developers.google.com/protocol-buffers/docs/proto3

于 2018-09-29T10:25:13.610 回答