Google Protocol Buffers是什么
Google Protocol Buffers 簡稱 Protobuf,它提供了一種靈活、高效、自動序列化結構數據的機制,可以聯想 XML,但是比 XML 更小、更快、更簡單。僅需要自定義一次你所需的數據格式,然后用戶就可以使用 Protobuf 編譯器自動生成各種語言的源碼,方便的讀寫用戶自定義的格式化的數據。與語言無關,與平臺無關,還可以在不破壞原數據格式的基礎上,依據老的數據格式,更新現有的數據格式。
Protobuf 的特點簡單總結如下幾點:
- 作用與 XML、json 類似,但它是二進制格式,性能好、效率高
- 代碼生成機制,易于使用
- 解析速度快
- 支持多種語言
- 向后兼容、向前兼容
- 缺點:可讀性差
目前,Protobuf 提供了兩個大版本: 2.x 版本和 3.x 版本。 2.x 版本最新的版本是 2.6.1,支持 C++、Java 和 Python 三種語言的API。 3.x 版本最新的版本是 3.0.0-beta-1,支持 C++、Java、Python、Ruby、JavaNano、Objective-x 和 C# 這幾種語言的 API。
Protobuf 如何工作
用戶在 .proto 文件中定義 message
來指定所需要序列化的數據格式。每一個 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 PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
從以上代碼來看,message
格式非常簡單。每種類型的 message
包含一個或者多個唯一編碼字段,每個字段由名稱和值類型組成,值類型可以是數字(整形或者浮點型)、布爾值、字符串、原始字節,甚至是其他的 message
(如上例所示)。Protobuf 允許 message
中包含 message
,以達到分層嵌套。message
中可以定義 optional 字段、required 字段和 repeated 字段。
定義好 message
后,運行 Protobuf 編譯器編譯 .proto 文件,就可以生成存取數據的相關類。這些類包括簡單的設置及讀取字段(比如 name()
和 set_name()
)的方法,也包括整個數據結構的 message
和原始字節之間的序列化/反序列化的轉換方法。舉個例子,如果你選擇的是 C++ 語言,運行 Protobuf 編譯器編譯以上 .proto 文件生成 Person 類。你就能使用這個類去填充、序列化、檢索 Person message
。如下代碼:
Person person;
person.set_name("zebra");
person.set_id(123);
person.set_email("zebra@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
接下來,用如下代碼來讀取 message
:
fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail" << person.email() << endl;
Protobuf 是易于擴展的,可以向后兼容,我們可以在 message
中添加新字段,在解析的時候,老版本的數據就會忽略新增加的字段。因此,如果現有通訊協議使用 Protobuf 做為其數據格式,我們可以直接擴展該通訊協議,而不必擔心著將會破壞現有的代碼。關于使用 .proto 文件生成目標代碼,后面將會介紹。
如何使用 Protobuf
我們使用 Protobuf 和 C++ 開發一個簡單的例子程序,該程序實現將一些結構化數據寫入文件和讀取文件。
首先下載 Protobuf 2.6.1 源碼。 下載頁面:Protobuf github
編譯安裝 Protobuf
Linux用戶編譯安裝如下:
tar -xzf protobuf-2.6.1.tar.gz
cd protobuf-2.6.1
./autogen
./configure --prefix=$INSTALL_DIR
make
make check
make install
如有問題,請認真閱讀 protobuf-2.6.1/README.md 和 protobuf-2.6.1/INSTALL.txt。
windows 用戶編譯安裝如下:
- 打開 protobuf-2.6.1/vsprojects/protobuf.sln。
- 將項目 libprotobuf 設置為啟動項目。
- 編譯 sln,Debug 模式和 Release 模式都編譯一下。
- 在 vsprojects/Debug 和 vsprojects/Release 目錄下會有 libprotobuf.lib、libprotobuf-lite.lib、libprotoc.lib 和 protoc.exe文件。
- 新建一個名為 “Install” 的文件夾,在 “Install” 目錄下再新建三個文件夾,分別是 “bin”、“include” 和 “lib”。將編譯生成的 protoc.exe 拷貝到 “bin” 目錄下,將編譯生成的 lib 庫文件拷貝到 “lib” 目錄下,將 protobuf/src 下的源文件拷貝 “include” 目錄下。
書寫 .proto 文件
定義一個關于個人信息的 .proto 文件,內容如下:
package tutorial;
message Person
{
required string name = 1;
required int32 age = 2;
optional string email = 3;
}
編譯 .proto 文件,生成 C++ 文件
使用 cmd 運行 proto.exe 生成我們的目標語言格式(C++)。命令行格式如下:
protoc.exe -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/person.proto
-I:指定 .proto 文件所在的路徑。
--cpp_out:指定生成的目標文件存在的路徑。
最后的參數是你需要生成的 .proto 文件名。
上例會生成 person.pb.h 和 person.pb.cc 的文件。person.pb.h 定義了 C++ 類的頭文件,person.pb.cc 是 C++ 類的實現文件。
使用 Protobuf 庫提供的 API 來編寫應用程序。
使用 Protobuf 庫來編寫應用程序時,需要包含 Protobuf 的頭文件,還需要鏈接庫文件。person.pb.h 頭文件定義了設置和讀取字段的方法,還有序列化和反序列化的方法,可以很方便的調用,可以參考上一章節的實例。