我的一位同事提出了在运行时生成协议缓冲区类的想法。含义:
这个想法是服务器将协议缓冲区的定义作为初始握手的一部分发送,并且Java应用程序在运行时生成该类并将其用于与服务器进行通信。
我不知道这是否是至关重要的想法,以及这种用例是否有实用程序。
谢谢
您所描述的内容实际上已经由C
++和Java中的协议缓冲区实现支持。您所需要做的就是传输一个FileDescriptorSet
,google/protobuf/descriptor.proto
其中包含定义了FileDescriptorProto
代表每个相关.proto
文件的,然后用于DynamicMessage
在接收端解释消息。
要FileDescriptorProto
在C ++中获取Foo
该文件中定义的给定消息类型,请执行以下操作:
google::protobuf::FileDescriptorProto file;
Foo::descriptor().file()->CopyTo(&file);
将FileDescriptorProto
定义所需类型的所有s以及它们导入的所有文件放入FileDescriptorSet
原型。请注意,您可以使用google::protobuf::FileDescriptor
(由返回的东西Foo::descriptor().file()
)遍历依赖关系,而不必显式命名每个依赖关系。
现在,发送FileDescriptorSet
给客户端。
在客户端上,用于FileDescriptor.buildFrom()
将每个转换FileDescriptorProto
为live
Descriptors.FileDescriptor
。您必须确保先构建依赖项,然后再构建依赖项,因为在构建依赖项时必须提供已经buildFrom()
构建的依赖项。
从那里,你可以使用FileDescriptor
的findMessageTypeByName()
找到Descriptor
您所关心的具体消息类型。
最后,您可以调用DynamicMessage.newBuilder(descriptor)
以为所讨论的类型构造一个新的构建器实例。
DynamicMessage.Builder
实现该Message.Builder
接口,该接口具有字段,getField()
并且setField()
可以动态地(通过指定相应的FieldDescriptor
s)操纵消息的字段。
同样,您可以调用DynamicMessage.parseFrom(descriptor,input)
解析从服务器收到的消息。
注意,它的一个缺点DynamicMessage
是它相对较慢。从本质上讲,它就像一种解释语言。生成的代码更快,因为编译器可以针对特定类型进行优化,而编译器DynamicMessage
必须能够处理任何类型。
但是,实际上没有解决方法。即使您运行了代码生成器并在运行时编译了该类,实际 使用
新类的代码仍将是您在知道要使用的类型之前编写的代码。因此,它仍然必须使用反射或类似反射的接口来访问消息,这比为特定类型手写代码要慢。
好吧,这取决于。客户端实际上将从服务器收到的此架构 做 什么?通过网络传输模式并不能使客户端与该协议版本兼容,客户端仍必须 了解
协议的含义。如果协议已在向后兼容的方式被改变,这几乎肯定意味着该 意思
协议的名称已更改,并且客户端代码必须更新(是否传输模式)。唯一可以期望客户端无需更新就可以继续工作的情况是,客户端仅执行仅取决于消息内容而不取决于消息含义的通用操作时,例如,客户端可以将消息转换为JSON不必知道这意味着什么。但这是相对不寻常的,尤其是在应用程序的客户端。这正是Protobufs默认不发送任何类型信息的原因-
因为它通常是无用的,因为如果接收者不知道 含义 ,则该架构是无关紧要的。
如果问题在于服务器正在向客户端发送消息,这些消息根本不打算被解释,而只是在稍后发送回服务器,则客户端根本不需要架构。只是将消息发送为bytes
,不必理会它。请注意,bytes
包含类型为编码的消息的字段在线路上Foo
看起来与类型实际声明为的字段完全相同Foo
。实际上,您可以针对.proto
文件的稍有不同的版本来编译客户端和服务器,在该版本中,客户端看到的是特定字段,bytes
而服务器将其视为子html" target="_blank">消息,从而避免了客户端知道该定义该子消息。``
试图使用Ionic 4中的协议缓冲区进行编码 我已经下载了协议并用它来生成一堆_pb.js文件,每个. proto文件一个。很好。 首先关注原型示例。这是示例代码: 我做了一些更改以匹配我的文件。更改proto文件的名称。但是我的proto文件中没有包名称。所以我只是使用了消息名称。首先这是我的. proto文件的开头: 下面是我修改后的代码: 这似乎不起作用。我的控制台显示: 我相信我已经成功地
问题内容: 我想做一个小的更改,深入到Java协议缓冲区对象的树中。 我可以使用该方法来制作一个新对象,该对象是旧对象的克隆并进行一些更改。 当深入执行此操作时,代码将变得难看: (这只是4个级别,我通常会处理5-8个级别。) 有没有更好的办法? 问题答案: 另一个选择是(我认为;已经有一段时间了): 注意,这没有任何效率。您仍在复制foo,bar,baz和quux。
问题内容: 我正在使用gSoap将旧式C 系统重构为SOA。我们遇到了一些性能问题(非常大的XML),因此我的领导要我看一下协议缓冲区。我做到了,它看起来非常酷(我们需要C 和Java支持)。但是协议缓冲区是仅用于序列化的解决方案,现在我需要将其发送到Java前端。从C ++和Java角度来看,我应该使用什么来通过HTTP(只是内部网络)发送那些序列化的内容? PS。另一个人试图加速我们的gSoa
当我尝试运行gtfs\u realtime\u pb2时,我遇到以下错误。py(通过google的协议缓冲区运行gtfs-realtime.proto生成的python代码): 这是指向我遇到问题的特定代码的链接:https://github.com/mattwigway/gtfsrdb 以及安装谷歌协议缓冲区的链接: https://developers.google.com/protocol-
两者都是序列化库,由谷歌开发人员开发。他们之间有什么大的区别吗?将使用协议缓冲区的代码转换为使用FlatBuffers需要大量工作吗?
在阅读这个相当长的问题之前,我提出了一个bughttps://github.com/GoogleCloudPlatform/python-docs-samples/issues/1103. 原型包和名称解析的留档状态 您可以使用其他定义。通过导入原始文件。导入另一个。在proto的定义中,您可以在文件的顶部添加一条import语句。 我的依赖于annotations.proto将HTTP/JSON