天道酬勤,学无止境

Protocol Buffers:如何在 Java 中解析 .proto 文件(Protocol Buffers: How to parse a .proto file in Java)

问题

我正在尝试动态解析 Java 中的给定 .proto 文件以解码 Protobuf 编码的二进制文件。

我有以下解析方法,其中“proto”字符串包含 .proto 文件的内容:

public static Descriptors.FileDescriptor parseProto (String proto) throws InvalidProtocolBufferException, Descriptors.DescriptorValidationException {
        DescriptorProtos.FileDescriptorProto descriptorProto = DescriptorProtos.FileDescriptorProto.parseFrom(proto.getBytes());
        return Descriptors.FileDescriptor.buildFrom(descriptorProto, null);
}

但是,在执行时,前一个方法会引发异常,并显示消息“协议消息标签的线路类型无效。”。 我使用来自 Google 的示例 .proto 文件,所以我想它是有效的:https://github.com/google/protobuf/blob/master/examples/addressbook.proto

这是堆栈跟踪:

15:43:24.707 [pool-1-thread-1] ERROR com.github.whiver.nifi.processor.ProtobufDecoderProcessor - ProtobufDecoderProcessor[id=42c8ab94-2d8a-491b-bd99-b4451d127ae0] Protocol message tag had invalid wire type.
com.google.protobuf.InvalidProtocolBufferException$InvalidWireTypeException: Protocol message tag had invalid wire type.
    at com.google.protobuf.InvalidProtocolBufferException.invalidWireType(InvalidProtocolBufferException.java:115)
    at com.google.protobuf.UnknownFieldSet$Builder.mergeFieldFrom(UnknownFieldSet.java:551)
    at com.google.protobuf.GeneratedMessageV3.parseUnknownField(GeneratedMessageV3.java:293)
    at com.google.protobuf.DescriptorProtos$FileDescriptorSet.<init>(DescriptorProtos.java:88)
    at com.google.protobuf.DescriptorProtos$FileDescriptorSet.<init>(DescriptorProtos.java:53)
    at com.google.protobuf.DescriptorProtos$FileDescriptorSet$1.parsePartialFrom(DescriptorProtos.java:773)
    at com.google.protobuf.DescriptorProtos$FileDescriptorSet$1.parsePartialFrom(DescriptorProtos.java:768)
    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.google.protobuf.DescriptorProtos$FileDescriptorSet.parseFrom(DescriptorProtos.java:260)
    at com.github.whiver.nifi.parser.SchemaParser.parseProto(SchemaParser.java:9)
    at com.github.whiver.nifi.processor.ProtobufDecoderProcessor.lambda$onTrigger$0(ProtobufDecoderProcessor.java:103)
    at org.apache.nifi.util.MockProcessSession.write(MockProcessSession.java:895)
    at org.apache.nifi.util.MockProcessSession.write(MockProcessSession.java:62)
    at com.github.whiver.nifi.processor.ProtobufDecoderProcessor.onTrigger(ProtobufDecoderProcessor.java:100)
    at org.apache.nifi.processor.AbstractProcessor.onTrigger(AbstractProcessor.java:27)
    at org.apache.nifi.util.StandardProcessorTestRunner$RunProcessor.call(StandardProcessorTestRunner.java:251)
    at org.apache.nifi.util.StandardProcessorTestRunner$RunProcessor.call(StandardProcessorTestRunner.java:245)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

任何的想法? 谢谢!

回答1

看起来您正在尝试使用FileDescriptorSet.parseFrom来填充FileDescriptorSet 。 这只会如果您提供的字节工作二进制protobuf的内容-这是说:编译架构。 您可以通过使用获得编译架构protoc命令行工具与--descriptor_set_out选项。 您现在实际传递的是构成文本模式的文本字节,这不是parseFrom期望的。

如果没有编译模式,您将需要一个运行时 .proto 解析器。 我不知道有一个适用于 Java 的; protobuf-net 包括一个 (protobuf-net.Reflection),但那是 C#/.NET。 如果没有可用的运行时 .proto 解析器,您需要改为 shell 执行protoc

回答2

从其他答案中提取,这是我正在开发的库中的工作 Kotlin 代码片段。 https://github.com/asarkar/okgrpc

private fun lookupProtos(
    protoPaths: List<String>,
    protoFile: String,
    tempDir: Path,
    resolved: MutableSet<String>
): List<DescriptorProtos.FileDescriptorProto> {
    val schema = generateSchema(protoPaths, protoFile, tempDir)
    return schema.fileList
        .filter { resolved.add(it.name) }
        .flatMap { fd ->
            fd.dependencyList
                .filterNot(resolved::contains)
                .flatMap { lookupProtos(protoPaths, it, tempDir, resolved) } + fd
        }
}

private fun generateSchema(
    protoPaths: List<String>,
    protoFile: String,
    tempDir: Path
): DescriptorProtos.FileDescriptorSet {
    val outFile = Files.createTempFile(tempDir, null, null)
    val stderr = ByteArrayOutputStream()
    val exitCode = Protoc.runProtoc(
        (protoPaths.map { "--proto_path=$it" } + listOf("--descriptor_set_out=$outFile", protoFile)).toTypedArray(),
        DevNull,
        stderr
    )
    if (exitCode != 0) {
        throw IllegalStateException("Failed to generate schema for: $protoFile")
    }
    return Files.newInputStream(outFile).use { DescriptorProtos.FileDescriptorSet.parseFrom(it) }
}

这个想法是使用 os72/protoc-jar 写出一个编译的架构/文件描述符。 然后使用FileDescriptorSet.parseFrom读取该文件,并对其依赖项进行递归。

回答3

不要使用 java String来保存 protobuf 负载。 问题在于String在幕后进行翻译,并对字符集做出假设。

Protobuf 适用于字节数组,数组中的确切表示必须保持不变。 往返String不起作用。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • protobuf详细介绍和使用
    一、protobuf初识 (一)protocol buffers 是什么? protocol buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小、更快、更为简单。你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏根据旧数据结构编译而成并且已部署的程序。 (二)它是如何工作的? 你可以通过在 .proto 文件中定义 protocol buffer message 类型,来指定你想如何对序列化信息进行结构化。每一个 protocol buffer message 是一个信息的小逻辑记录,包含了一系列的 name-value 对。这里有一个非常基础的 .proto 文件样例,它定义了一个包含 "person" 相关信息的 message: message Person { required string name = 1; required int32 id = 2; optional string email = 3; ​ enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } ​ message PhoneNumber { required string number = 1; optional
  • 如何使用 Gradle 构建 Google 协议缓冲区和 Kotlin?(How to build Google protocol buffers and Kotlin using Gradle?)
    问题 我正在尝试使用 Gradle 构建一个同时使用 Google 协议缓冲区和 Kotlin 的项目。 我希望 proto 文件编译成 Java 源代码,然后从我的 Kotlin 代码中调用它。 我的源文件是这样排列的: src/main/proto/*.proto src/main/kotlin/*.kt src/test/kotlin/*.kt 这是我的build.gradle文件: version '1.0-SNAPSHOT' apply plugin: 'kotlin' apply plugin: 'java' apply plugin: 'com.google.protobuf' repositories { mavenCentral() maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } } buildscript { ext.kotlin_version = '1.1-M02' repositories { mavenCentral() maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } } dependencies { classpath 'com.google.protobuf:protobuf-gradle-plugin:0
  • 解析协议缓冲区,用 Java 编写并用 Python 读取(Parsing Protocol Buffers, written in Java and read in Python)
    问题 我正在处理协议缓冲区已用 Java 写入的情况,但我必须使用 Python 读取它们。 我有 .proto 文件,我使用 protoc 编译它,并生成了 python 类文件。 proto 文件有多个消息,例如: message ABC { optional int64 id = 1 [default = -1]; optional int64 hello6 = 2; optional bool hello5 = 3 [default = true]; optional int32 hello4 = 4; optional int64 hello3 = 5; optional int64 hello2 = 6; optional int64 duration = 7; } message DEF { optional int64 hello = 1; repeated ABC abc = 5; repeated String xyz = 6; } 在使用 .ParseFromString 在 python 中解析时。 我收到错误: google.protobuf.message.DecodeError:标签的线类型无效。 我认为这个问题是因为没有明确的分隔符,知道如何解决吗? 回答1 我有类似的问题,这对我有用: 在 Java 中,您可以:
  • 深入理解 ProtoBuf 原理与工程实践(概述)
    ProtoBuf 作为一种跨平台、语言无关、可扩展的序列化结构数据的方法,已广泛应用于网络数据交换及存储。随着互联网的发展,系统的异构性会愈发突出,跨语言的需求会愈加明显,同时 gRPC 也大有取代Restful之势,而 ProtoBuf 作为g RPC 跨语言、高性能的法宝,我们技术人有必要 深入理解 ProtoBuf 原理,为以后的技术更新和选型打下基础。 我将过去的学习过程以及实践经验,总结成系列文章,与大家一起探讨学习,希望大家能有所收获,当然其中有不正确的地方也欢迎大家批评指正。 本系列文章主要包含: 深入理解 ProtoBuf 原理与工程实践(概述) 深入理解 ProtoBuf 原理与工程实践(编码) 深入理解 ProtoBuf 原理与工程实践(序列化) 深入理解 ProtoBuf 原理与工程实践(工程实践) 一、什么是ProtoBuf ProtoBuf(Protocol Buffers)是一种跨平台、语言无关、可扩展的序列化结构数据的方法,可用于网络数据交换及存储。 在序列化结构化数据的机制中,ProtoBuf是灵活、高效、自动化的,相对常见的XML、JSON,描述同样的信息,ProtoBuf序列化后数据量更小、序列化/反序列化速度更快、更简单。 一旦定义了要处理的数据的数据结构之后,就可以利用ProtoBuf的代码生成工具生成相关的代码。只需使用 Protobuf
  • 使用正确的 .proto 文件时,无法解析 python 中的协议缓冲区文件(Cannot parse a protocol buffers file in python when using the correct .proto file)
    问题 (见底部更新) Tilemaker 是一个 OpenStreetMap 程序,用于从 OSM pbf 数据文件生成 Mapbox 矢量瓦片(它们本身就是协议缓冲区(pbf)文件)。 我已经编译它并用它来创建一个矢量切片目录。 我无法在 Python 中解析这些文件。 我创建了矢量图块: tilemaker input.pbf --output=tiles/ 然后我创建了一个简单的python程序,基于谷歌的Protocol Buffers Python Tutorial以这种方式: 编译.proto文件: mkdir py touch py/__init__.py protoc --proto_path=include --python_out=./py ./include/osmformat.proto protoc --proto_path=include --python_out=./py ./include/vector_tile.proto 这个 python 程序pyread.py不起作用: import sys import py.vector_tile_pb2 with open(sys.argv[1]) as fp: pbf_file_contents = fp.read() tile = py.vector_tile_pb2.Tile() tile
  • 将协议缓冲区集成到 Maven2 构建中(Integrate Protocol Buffers into Maven2 build)
    问题 我正在一个现有的、相当普通的 Maven 2 项目中试验协议缓冲区。 目前,我每次需要更新生成的源时都会调用一个 shell 脚本。 这显然很麻烦,因为我希望在每次构建之前自动生成源代码。 希望不要诉诸可耻的hackery。 所以,我的问题有两个方面: 远景:是否有 Maven 2 的“协议缓冲区插件”可以以自动方式实现上述目标? 谷歌代码上有一个分支,其作者似乎已经尝试实现这样的插件。 不幸的是,它没有通过代码审查或被合并到 protobuf 主干中。 因此,该插件的状态未知。 可能更现实:缺少实际的插件,我还能如何从我的 Maven 2 构建中调用protoc ? 我想我可以将我现有的 shell 脚本连接到antrun调用或类似的东西中。 个人经验最受赞赏。 回答1 您将在 Protocol Buffers 讨论组的 Protocol Buffers Compiler Maven Plug-In 线程中的 Protocol Buffers 存储库中找到有关该插件的一些信息。 我的理解是它可用但缺乏测试。 我想试一试。 或者你可以只使用antrun插件(从上面提到的线程粘贴的antrun ): <build> <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <executions>
  • 解析没有.proto文件的Google协议缓冲区数据报?(Parse Google Protocol Buffers datagram without .proto file?)
    问题 是否有可能解析传入的Google协议缓冲区数据报而没有任何.proto文件? 我现在只是使用协议缓冲区对其进行了序列化,但对IDL文件一无所知。 我正在寻找一种通过某种反射来迭代任何值的方法? 这可能吗? 谢谢! 回答1 protoc --decode_raw < my_file 检查输出时,需要考虑以下事项: 没有字段名可见,只有标签号可见。 所有varint字段均显示为整数。 大多数类型都可以,但是sint *将以“ zigzagged”格式显示。 双打和浮点将显示为十六进制。 字节,字符串字段和子消息都显示相同,即只是一堆字节。 如果要以编程方式解码消息,则可以在使用上述方法弄清楚字段的含义之后编写自己的.proto文件。
  • 在协议缓冲区中使用小数和日期时间的最佳方法是什么?(What the best ways to use decimals and datetimes with protocol buffers?)
    问题 我想找出存储一些未包含在协议缓冲区支持的列表中的常见数据类型的最佳方式。 日期时间(秒精度) 日期时间(毫秒精度) 固定精度的小数具有可变精度的小数很多 bool 值(如果你有很多,看起来由于它们的标签,每个值都会有 1-2 个字节的开销。 同样的想法是将它们非常容易地映射到相应的 C++/Python/Java 数据类型。 回答1 protobuf 的设计原理最有可能将数据类型支持保持为“本机”,以便将来可以轻松采用新语言。 我想他们可以提供内置消息类型,但你在哪里划线? 我的解决方案是创建两种消息类型: DateTime TimeSpan 这只是因为我来自 C# 背景,这些类型被认为是理所当然的。 回想起来, TimeSpan和DateTime可能有点矫枉过正,但这是一种避免从 h/m/s 转换为 s 的“廉价”方式,反之亦然; 也就是说,实现一个效用函数会很简单,例如: int TimeUtility::ToSeconds(int h, int m, int s) Bklyn,指出堆内存用于嵌套消息; 在某些情况下,这显然非常有效——我们应该始终了解内存是如何使用的。 但是,在其他情况下,这可能不太重要,我们更担心实现的难易程度(我认为这是 Java/C# 哲学)。 将非内在类型与 protobuf TextFormat::Printer一起使用还有一个小缺点;
  • 如何使用协议缓冲区反序列化 Java 中的文件?(How to de-serialize the file in Java by using Protocol-buffer?)
    问题 想在 C# 中创建一个序列化的文件,然后想在 Java 中反序列化它。 为此,我正在使用协议缓冲区库。 我想在这里完成: 在 C# 中,我添加了 protobuf-net.dll 并且要序列化的类表示为: 人物.cs [ProtoBuf.ProtoContract] public class Person { [ProtoBuf.ProtoMember(1)] public int Id {get;set;} [ProtoBuf.ProtoMember(2)] public string Name { get; set; } } 在 main 方法中,像这样序列化它: var person = new Person { Id = 12345, Name = "Fred", }; using (var file = File.Create("somepath\\person.bin")) { Serializer.Serialize(file, person); } 这个 bin 文件我复制并拉入 ecilpse 文件系统 - android /sdcard 并试图反序列化它 在日食-JAVA中, 添加了 protobuf.jar、外部库和创建的 person.proto 文件,其中包含: message Person{ required int32 Id=1
  • 在Objective-C中使用协议缓冲区(Using Protocol Buffers with Objective-C)
    问题 在Objective-C中开发应用程序时,有人使用过Google的协议缓冲区吗? 当前是否有任何将.proto文件编译成Objective-C的项目,所有Google文档都仅引用Java,C ++或Python。 回答1 我一直在研究Cyrus的项目。 它基于protobuf的2.3和作品作为protoc插件( protoc-gen-objc ),而不需要修改protobuf的分布。 您可以在GitHub上找到它作为protobuf-obj项目。 回答2 “第三方”页面列出了此Objective-C端口。 不幸的是,该项目目前似乎是空的,但无论如何还是令人鼓舞的。 我曾听说过该项目的内部传闻,但在今天之前还没有将其视为开源项目。 您可以与项目所有者(Cyrus Najmabadi)联系,以询问有关此问题的信息... (琐碎的小事-Cyrus在加入Google之前曾在Microsoft的C#团队工作。) 回答3 这可能有帮助,也可能没有帮助,但是Apache Thrift(最初由Facebook开发)支持Cocoa,并且似乎有人尝试在iPhone中使用它。 Thrift正式支持更多语言。 但是协议缓冲区的兴趣是堆栈溢出的5倍,所以谁知道在维护方面它是否是一个很好的替代品-更不用说与您自己的项目的兼容性了! 不过,也许值得考虑。 我只是问了一个相关问题,如果它能得到很好的回答
  • 将 Google Protocol Buffers .proto 文件集成到 Visual C++ 2010(Integrate Google Protocol Buffers .proto files to Visual C++ 2010)
    问题 我在我的Visual Studio项目文件中添加了一个自定义构建步骤,它从 .proto 输入文件生成google protobuf .h/.cc 文件。 但是我一直想知道是否可以仅在 proto 文件的内容发生更改时才开始编译? 有没有办法从自定义构建步骤中准确地告诉 VisualStudio? 将 proto 文件集成到 Visual Studio 构建解决方案中的最佳方法是什么? 目前,在每次构建时都会更新 .proto 文件,然后也会更新输出 .h/.cc 文件的时间戳……然后重新编译所有依赖于此的文件。 有没有更好的方法来解决它,同时仍然直接从 Visual Studio 构建它们? 回答1 也许这有帮助。 特别是看看 Igor Zavoychinskiy 的帖子: 这个讨厌的问题的解决方案实际上很简单:在输出部分你应该指定完整路径。 这在任何地方都没有明确说明,但没有这个检查器就无法找到文件,因此,假设它们不存在。 例如对于 protobuffers 编译输出部分将是这样的: $(InputDir)\$(InputName).pb.cc;$(InputDir)\$(InputName).pb.h 和(也许?)kmote00: ... 底线:我只需要确保我的“输出”条目与(用户定义的)“OutputFile”属性中的默认值完全匹配。 (值得庆幸的是
  • 在带有 Protocol Buffers 的项目中使用 Proguard 有哪些特点?(What are features of using Proguard in project with Protocol Buffers?)
    问题 我有一个使用 Google Protocol Buffers 的项目。 一旦我尝试使用 ProGuard 对其进行混淆,似乎 protobuf 会导致问题。 我将所有自己的类打包到mybuildedclasses.jar 。 谷歌代码打包成protbuf.jar mybuildedclasses.jar protobuf.jar other external jars 之后,我试图混淆mybuildedclasses.jar 。 配置文件与此类似。 最终所有的罐子都被包装在另一个胖罐子里。 我运行程序,一旦尝试发送消息,就会打印这种异常。 Caused by: java.lang.RuntimeException: Generated message class "org.mypackage.messages.Control$MessageControlHandCard$Builder" missing method "getCardId". at com.google.protobuf.GeneratedMessage.getMethodOrDie(GeneratedMessage. java:1366) at com.google.protobuf.GeneratedMessage.access$1(GeneratedMessage.java:1 361) at com
  • 为什么在协议缓冲区3中删除了必需和可选的内容(Why required and optional is removed in Protocol Buffers 3)
    问题 我最近将gRPC与proto3 gRPC使用,并且我注意到在新语法中已删除了required和optional 。 谁能解释一下为什么在proto3中删除了必需/可选的内容? 此类约束似乎对于使定义更健壮似乎是必需的。 语法proto2: message SearchRequest { required string query = 1; optional int32 page_number = 2; optional int32 result_per_page = 3; } 语法proto3: syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; } 回答1 的实用性required已在许多争论和口水战的心脏。 双方都有大营地。 一个营地喜欢保证存在一个价值,并愿意忍受它的局限性,但是另一个营地则感到required危险或无益,因为它不能安全地添加或删除。 让我解释更多为什么required谨慎使用required字段的原因。 如果您已经在使用原型,则无法添加必填字段,因为旧的应用程序不会提供该字段,并且应用程序通常无法很好地处理故障。 您可以确保首先升级所有旧的应用程序,但是容易出错
  • 使用协议缓冲区的Python项目,部署问题(Python project using protocol buffers, Deployment issues)
    问题 我有一个Python项目,该项目使用setuptools进行部署,并且我主要遵循有关项目结构的本指南。 该项目使用Google协议缓冲区来定义网络消息格式。 我的主要问题是如何使setup.py在安装过程中调用protoc-compiler来将定义构建到_pb2.py文件中。 在此问题中,建议仅将生成的_pb2.py文件与项目一起分发。 尽管这可能适用于非常相似的平台,但我发现有几种情况不起作用。 例如,当我在使用Anaconda Python的Mac上进行开发并将复制的_pb2.py和项目的其余部分复制到运行Raspbian的Raspberry Pi时,总是会出现_pb2.py模块引起的导入错误。 但是,如果我在Pi上重新编译.proto文件,则该项目将按预期工作。 因此,分发编译的文件似乎不是一种选择。 有点在这里寻找工作和最佳实践的解决方案。 可以假定协议编译器已安装在目标平台上。 编辑: 由于人们要求失败的原因。 在Mac上,protobuf版本为2.6.1。 而在Pi上是2.4.1。 显然,生成的协议编译器输出所使用的内部API已更改。 输出基本上是: File "[...]network_manager.py", line 8, in <module> import InstrumentControl.transports.serial_bridge
  • protocal buffers 官方文档学习
    protocal buffers 官方文档学习 文章目录 protocal buffers 官方文档学习1.What are protocol buffers?2.选择你喜欢的语言3.怎么开始,步骤3.1下载和安装protocal buffer 编译器3.2阅读入门指南3.2.1 开发者指南3.2.1.1 怎么开始?3.2.1.2为什么不使用xml?3.2.1.3介绍一下protobuf3 3.2.2 proto3语言3.2.2.1 定义一个消息类型3.2.2.2 字段值类型3.2.2.3枚举3.2.2.4 使用消息类型3.2.2.5嵌套类型3.2.2.6 更新一个消息时怎么办3.2.2.7 未知的字段3.2.2.8 any 类型3.2.2.9Oneof3.2.2.11定义服务3.2.2.12可选项 3.2.3编码风格指南3.2.3.1标准文件格式3.2.3.2 消息和字段名称3.2.3.4 重复字段3.2.3.5 枚举3.2.3.4 重复字段3.2.3.5 枚举 前言:最近在做一个项目,负责通讯这块。采用技术是netty+protobuf 在安卓端和c#端进行通信。项目快差不多了,做一下沉淀,翻译一下protbuf文档,和自己的项目工程实践。工程实践代码可以看我的另一篇博文,是接着写的。 1.What are protocol buffers? protocal
  • Google协议缓冲区和HTTP(Google Protocol Buffers and HTTP)
    问题 我正在使用gSoap将旧式C ++系统重构为SOA。 我们遇到了一些性能问题(非常大的XML),因此我的领导要我看一下协议缓冲区。 我做到了,它看起来很酷(我们需要C ++和Java支持)。 但是,协议缓冲区是仅用于序列化的解决方案,现在我需要将其发送到Java前端。 从C ++和Java角度来看,我应该使用什么来通过HTTP(只是内部网络)发送那些序列化的内容? PS。 另一个人试图加快我们的gSoap解决方案的速度,我只对协议缓冲区感兴趣。 回答1 当然,您甚至可以使用HTTP请求或HTTP响应发送二进制有效负载。 只需将协议缓冲区的字节直接写入请求/响应中,并确保将内容类型设置为“ application / octet-stream”。 客户端和服务器应该能够轻松处理其余的工作。 我认为您不需要任何特别的东西。 回答2 ProtoBuf是一个二进制协议。 它不能与SOAP很好地混合使用。 我建议您要么坚持使用gSOAP,要么完全转换为ProtoBuf。 使用protoBuf,您可以按照以下特殊格式定义协议, message Product { required string id = 1; required string description = 2; required int32 quantity = 3; optional bool discontinued =
  • Google 协议缓冲区 - 用户定义的 Java 对象作为消息字段(Google protocol buffers - user defined java objects as messages fields)
    问题 我从昨天开始学习谷歌协议缓冲区并有一个问题: 我可以使用用户定义的 java 类作为 .proto 文件中的字段类型吗? 让我用以下详细信息澄清我的问题: 1 - 我有以下 java 类“MyComplexClass.java”: package mypackage; import another.package1.ClassA; import another.package2.ClassB; public class MyComplexClass { private ClassA var1; private ClassB var2; public MyComplexClass(ClassA X, ClassB Y) this.var1 = X; this.var2 = Y; } 2- 现在我想序列化“MyComplexClass.java”类的一个实例。 为此,我想在 .proto 文件中描述如下消息: message myMessageToBeSerialized { required ***MyComplexClass*** intanceOfComplexClass = 1; } 是否可以使用用户定义的类MyComplexClass作为字段类型? 还是只允许使用标量类型? 任何帮助,将不胜感激。 提前致谢。 贺拉斯 回答1 不可以。只能使用定义为协议缓冲区的类型。
  • Go中的gRPC简介
    给使用 Go 语言的初学者的 gRPC 概述 文章目录 RPC它是怎么工作的? 用例Protocol Buffers安装 gRPC实现 总结架构向后兼容性架构演变验证语言互操作性 RPC RPC 是用于 软件应用之间点对点通信 的 网络编程模型 或是 进程间通信技术。 RPC 是一种 协议,一个程序能够使用该协议,对位于另外一台计算机中的程序请求服务,而无需了解网络的详细信息。 RPC 代表 “远程过程调用”,它是一种 客户端 - 服务器交互 的形式 - 调用者是客户端,执行者是服务器 - 通常通过 " 请求 - 响应消息传递系统 " 实现。 客户端运行时程序,知道如何去寻址远程服务器应用程序,以及通过网络发送请求远程过程的消息。类似的,服务器包括与远程过程本身的运行时程序和存根。 它是怎么工作的? RPC 工作的方式是,发送方或者客户端以过程、函数或者方法调用的形式创建对 RPC 进行转换和发送的远程服务器的请求。当远程服务器接收到请求时,它会将响应发送回客户端,然后应用程序继续其进程。 RPC 工作的方式是,发送方或者客户端以过程、函数或者方法调用的形式创建对 RPC 进行转换和发送的远程服务器的请求。当远程服务器接收到请求时,它会将响应发送回客户端,然后应用程序继续其进程。 用例 我们将实现一个 Gravatar 服务,用以 生成 URLs,其包含相关邮件地址的 MD5 哈希
  • Google 协议缓冲区和 servlet(Google protocol buffers and servlets)
    问题 我想知道如何使用谷歌协议缓冲区来接受请求并将响应发送回客户端? 我正在考虑编写一个接受请求的 servlet。 以下思路是否是实现这一点的正确方法: 1. 有一个 .proto 文件,它是传入请求的消息定义。 2. 编写一个 servlet 来接受这个请求,执行各种任务,比如查询数据库,然后发送响应。 此响应是否需要单独的 .proto 消息定义,其中包含构成响应的所有字段? 3. 客户端是否会调用我的 servlet 的 doGet() 方法并传递请求,然后它应该返回一个响应作为 protobuff 对象? 任何建议或想法将不胜感激。 回答1 通常,您需要一个请求消息和一个响应消息,是的。 您可能还需要一个方法名称来描述操作——这当然是内置 PB 服务的工作方式。 客户端不会调用 doGet() - 它会发出请求(可能是 POST 而不是 GET)并且您的 servlet 会接收它。 现在,理想情况下,您可以拥有一个通用的“ProtocolBufferServlet”,它可以通过将请求交给实现适当接口的服务来为请求提供服务。 我建议您查看协议缓冲区服务和 Java 服务生成代码的文档以获取更多信息。 您可以实现一个在 servlet 上工作的RpcChannel ,或者让客户端直接进行 HTTP 发布。 您可能会在服务器端使用某种依赖注入来告诉 servlet
  • 如何在协议缓冲区中设计未来的附加枚举值?(How to design for a future additional enum value in protocol buffers?)
    问题 协议缓冲区的一个吸引人的特性是它允许您扩展消息定义而不会破坏使用旧定义的代码。 在根据文档的枚举的情况下: 具有枚举类型的字段只能将一组指定的常量中的一个作为其值(如果您尝试提供不同的值,解析器会将其视为未知字段) 因此,如果您扩展枚举并使用新值,那么旧代码中具有该类型的字段将是未定义的或具有其默认值(如果有)。 知道将来枚举可能会添加额外的值,处理这个问题的好策略是什么? 想到的一种方法是定义枚举的“未定义”成员并将其设为默认值,然后旧代码将知道它已发送了无法解释的内容。 这是明智的,有没有更好的方法来处理这种情况? 回答1 是的,最好的方法是使枚举中的第一个值类似于UNKNOWN = 0 。 然后旧程序读取带有他们无法识别的枚举值的 protobuf 会将其视为UNKNOWN并希望他们可以合理地处理它,例如通过跳过该元素。 如果您想这样做,您还需要将 enum 设为optional not required 。 required ,一般来说,意味着“我宁愿程序只是中止而不是处理它不理解的东西。” 请注意,它必须是 proto 源中声明的第一个值- 只是零值不会使其成为默认值。