Protocol Buffer

1、什么是 Protocol Buffers?

Protocol Buffers (protobuf) 是一种序列化结构化数据的方法,由 Google 开发。它们提供了一种与语言无关、与平台无关且可扩展的机制,用于高效序列化结构化数据。

  • Protocol Buffers 中的数据结构是在架构文件(.proto 文件)中使用简单的与语言无关的接口定义语言 (IDL) 定义的。
  • Protocol Buffers 将数据序列化为二进制格式。这种二进制格式可通过网络高效传输,并且与基于文本的格式(如 XML 或 JSON)相比,序列化和反序列化速度更快。
  • Protocol Buffers 支持多种编程语言,包括 C++、Java、Python、Go 等。
  • Google 提供了编译器工具(protobuf 编译器),这些工具基于 .proto 架构文件生成这些语言的数据访问类和序列化/反序列化代码。
  • Protocol Buffers 支持向后和向前兼容性。可以将新字段添加到架构中,而不会中断可能仍在使用旧版本架构的现有客户端或服务器。
  • 这使得在大型系统中随时间推移演变数据格式变得更加容易。
  • Protocol Buffers 通常用于对结构化数据进行高效序列化、传输和存储至关重要的场景。这包括网络通信协议(例如 gRPC,默认情况下使用 protobuf)、在数据库中存储数据,以及设计需要有效处理大量数据的 API。

2、示例实现

Protocol Buffers支持以 C++、C#、Dart、Go、Java 和 科特林 / Objective-C、Python 和 Ruby。使用 proto3,您还可以使用 PHP。

复制代码
message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;
}

原型定义

复制代码
// Java code
Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("[email protected]")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

使用生成的类来持久保存数据。

复制代码
// C++ code
Person john;
fstream input(argv[1],
    ios::in | ios::binary);
john.ParseFromIstream(&input);
id = john.id();
name = john.name();
email = john.email();

使用生成的类解析持久化数据

复制代码
// C++ code
Person john;
fstream input(argv[1],
    ios::in | ios::binary);
john.ParseFromIstream(&input);
id = john.id();
name = john.name();
email = john.email();

3、protobuf-net

protobuf-net是用于.NET代码的基于契约的序列化程序,它以Google设计的"protocol buffers"序列化格式写入数据,适用于大多数编写标准类型并可以使用属性的.NET语言。

protobuf-net可通过NuGet安装程序包,也可直接访问github下载源码:https://github.com/protobuf-net/protobuf-nethttps://github.com/protobuf-net/protobuf-net 下面的代码参考:C#中protobuf-net的编码结构及使用方法 - 二次元攻城狮 - 博客园

复制代码
using System;
using System.IO;

/// <summary>
/// ProtoBuf-Net扩展方法类
/// </summary>
public static class ProtoBufExtension
{
    /// <summary>
    /// 将对象实例序列化为字符串(Base64编码格式)------ProtoBuf
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="obj">对象实例</param>
    /// <returns>字符串(Base64编码格式)</returns>
    public static string SerializeToString_PB<T>(this T obj)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(ms, obj);
            return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
        }
    }

    /// <summary>
    /// 将字符串(Base64编码格式)反序列化为对象实例------ProtoBuf
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="txt">字符串(Base64编码格式)</param>
    /// <returns>对象实例</returns>
    public static T DeserializeFromString_PB<T>(this string txt)
    {
        byte[] arr = Convert.FromBase64String(txt);
        using (MemoryStream ms = new MemoryStream(arr))
            return ProtoBuf.Serializer.Deserialize<T>(ms);
    }

    /// <summary>
    /// 将对象实例序列化为字节数组------ProtoBuf
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="obj">对象实例</param>
    /// <returns>字节数组</returns>
    public static byte[] SerializeToByteAry_PB<T>(this T obj)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(ms, obj);
            return ms.ToArray();
        }
    }

    /// <summary>
    /// 将字节数组反序列化为对象实例------ProtoBuf
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="arr">字节数组</param>
    /// <returns></returns>
    public static T DeserializeFromByteAry_PB<T>(this byte[] arr)
    {
        using (MemoryStream ms = new MemoryStream(arr))
            return ProtoBuf.Serializer.Deserialize<T>(ms);
    }

    /// <summary>
    /// 将对象实例序列化为二进制文件------ProtoBuf
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="obj">对象实例</param>
    /// <param name="path">文件路径(目录+文件名)</param>
    public static void SerializeToFile_PB<T>(this T obj, string path)
    {
        using (var file = File.Create(path))
        {
            ProtoBuf.Serializer.Serialize(file, obj);
        }
    }

    /// <summary>
    /// 将二进制文件反序列化为对象实例------ProtoBuf
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path"></param>
    /// <returns></returns>
    public static T DeserializeFromFile_PB<T>(this string path)
    {
        using (var file = File.OpenRead(path))
        {
            return ProtoBuf.Serializer.Deserialize<T>(file);
        }
    }
}

使用参考

复制代码
static void Main(string[] args)
{

    var person = new Person
    {
        Id = 12345,
        Name = "Fred",
        Address = new Address
        {
            Line1 = "Flat 1",
            Line2 = "The Meadows"
        }
    };

    string str = person.SerializeToString_PB();            
    var strPerson = str.DeserializeFromString_PB<Person>();
    Console.WriteLine("序列化结果(字符串):" + str);

    var arr = person.SerializeToByteAry_PB();
    var arrPerson = arr.DeserializeFromByteAry_PB<Person>();
    Console.WriteLine("序列化结果(字节数组):" + BitConverter.ToString(arr));

    string path = "person.bin";            
    person.SerializeToFile_PB(path);
    var pathPerson = path.DeserializeFromFile_PB<Person>();
    Console.WriteLine("序列化结果(二进制文件):" + BitConverter.ToString(File.ReadAllBytes(path)));

    Console.ReadLine();
}

序列化结果

复制代码
序列化结果(字符串):CLlgEgRGcmVkGhUKBkZsYXQgMRILVGhlIE1lYWRvd3M=
序列化结果(字节数组):08-B9-60-12-04-46-72-65-64-1A-15-0A-06-46-6C-61-74-20-31-12-0B-54-68-65-20-4D-65-61-64-6F-77-73
序列化结果(二进制文件):08-B9-60-12-04-46-72-65-64-1A-15-0A-06-46-6C-61-74-20-31-12-0B-54-68-65-20-4D-65-61-64-6F-77-73
相关推荐
virelin_Y.lin1 小时前
系统与网络安全------弹性交换网络(2)
网络·安全·web安全·链路聚合·lacp·eth-trunk
天狼12221 小时前
第5章-1 优化服务器设置
运维·服务器·adb
浪裡遊3 小时前
Linux常用指令
linux·运维·服务器·chrome·功能测试
SugarPPig4 小时前
PowerShell 查询及刷新环境变量
服务器
EasyDSS6 小时前
视频监控从安装到优化的技术指南,视频汇聚系统EasyCVR智能安防系统构建之道
大数据·网络·网络协议·音视频
我的作业错错错6 小时前
搭建私人网站
服务器·阿里云·私人网站
rufeike6 小时前
UDP协议理解
网络·网络协议·udp
王景程7 小时前
如何测试短信接口
java·服务器·前端
江理不变情7 小时前
海思ISP调试记录
网络·接口隔离原则
微网兔子7 小时前
伺服器用什么语言开发呢?做什么用什么?
服务器·c++·后端·游戏