gRPC-Protocol基础知识-C#篇

本文使用协议缓冲区语言的proto3版本,为C#程序员提供了使用协议缓冲区的基本介绍。 通过创建一个简单的示例应用程序,展示了如何

在.proto文件中定义消息格式。

使用协议缓冲区编译器。

使用C#协议缓冲区API写入和读取消息。

这不是在C#中使用协议缓冲区的全面指南。 有关更多详细的参考信息,请参阅《协议缓冲区语言指南》,《 C#API参考》,《 C#生成的代码指南》和《编码参考》。

为什么要使用协议缓冲区?

我们将使用的示例是一个非常简单的“地址簿”应用程序,该应用程序可以在文件中读写人的联系方式。通讯录中的每个人都有一个姓名,一个ID,一个电子邮件地址和一个联系电话。

您如何像这样序列化和检索结构化数据?有几种方法可以解决此问题:

将.NET二进制序列化与System.Runtime.Serialization.Formatters.Binary.BinaryFormatter和关联的类一起使用。面对变化,这最终变得非常脆弱,在某些情况下,数据大小非常昂贵。如果您需要与为其他平台编写的应用程序共享数据,它也不是很好。
您可以发明一种将数据项编码为单个字符串的临时方法,例如将4个整数编码为“ 12:3:-23:67”。尽管确实需要编写一次性的编码和解析代码,但是这是一种简单且灵活的方法,而且解析带来的运行时成本很小。这对于编码非常简单的数据最有效。
将数据序列化为XML。由于XML是人类(一种)可读的,并且存在用于多种语言的绑定库,因此这种方法可能非常有吸引力。如果要与其他应用程序/项目共享数据,这可能是一个不错的选择。但是,众所周知,XML占用大量空间,对它进行编码/解码会给应用程序带来巨大的性能损失。同样,导航XML DOM树比通常导航类中的简单字段要复杂得多。
协议缓冲区是灵活,高效,自动化的解决方案,可以准确地解决此问题。使用协议缓冲区,您可以编写要存储的数据结构的.proto描述。由此,协议缓冲区编译器创建了一个类,该类以有效的二进制格式实现协议缓冲区数据的自动编码和解析。生成的类为构成协议缓冲区的字段提供获取器和设置器,并以协议为单位来处理读写协议缓冲区的详细信息。重要的是,协议缓冲区格式支持随时间扩展格式的想法,以使代码仍可以读取以旧格式编码的数据。

在哪里找到示例代码?

我们的示例是一个命令行应用程序,用于管理使用协议缓冲区编码的地址簿数据文件。 命令AddressBook(请参阅:Program.cs)可以将新条目添加到数据文件或解析数据文件并将数据打印到控制台。

您可以在GitHub存储库的examples目录和csharp / src / AddressBook目录中找到完整的示例。

定义协议格式

要创建地址簿应用程序,您需要以.proto文件开头。 .proto文件中的定义很简单:您为要序列化的每个数据结构添加一条消息,然后为消息中的每个字段指定名称和类型。 在我们的示例中,定义消息的.proto文件是addressbook.proto。

.proto文件以程序包声明开头,这有助于防止不同项目之间的命名冲突。

syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto";

在C#中,如果未指定csharp_namespace,则将生成的类放置在与程序包名称匹配的名称空间中。 在我们的示例中,指定了csharp_namespace选项以覆盖默认值,因此生成的代码使用Google.Protobuf.Examples.AddressBook的命名空间而不是Tutorial。

option csharp_namespace = "Google.Protobuf.Examples.AddressBook";

接下来,您将拥有消息定义。 消息只是包含一组类型字段的汇总。 许多标准的简单数据类型可用作字段类型,包括bool,int32,float,double和string。 您还可以通过使用其他消息类型作为字段类型来为消息添加更多的结构。

message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; }

在上面的示例中,Person消息包含PhoneNumber消息,而AddressBook消息包含Person消息。您甚至可以定义嵌套在其他消息中的消息类型-如您所见,PhoneNumber类型在Person内部定义。如果希望您的字段之一具有预定义的值列表之一,也可以定义枚举类型-在这里您要指定电话号码可以是MOBILE,HOME或WORK之一。

每个元素上的“ = 1”,“ = 2”标记标识该字段在二进制编码中使用的唯一“标记”。标签编号1至15与较高的编号相比,编码所需的字节减少了一个字节,因此,为了进行优化,您可以决定将这些标签用于常用或重复的元素,而将标签16和更高的标签用于较少使用的可选元素。重复字段中的每个元素都需要重新编码标签号,因此重复字段是此优化的最佳候选者。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfzwf.html