跨語言平臺編程,使用SOAP的話,該方式是使用xml的方式傳輸,會大大增長網絡的IO,並且xml的解析複雜,下降報文的解析性能。java
message LogonReqMessage{ required int64 actID=1; required string passwd=2; }
關鍵說明:python
message
是消息的關鍵字LogonReqMessage
是消息名字,至關於java的類名required
前綴表示該字段未必要字段,序列化先後必須賦值的字段。protobuf還存在兩個相似的關鍵字optional
和repeated
主要用於表示數組字段。1
和2
表示不一樣的字段在序列化先後的二進制中的佈局位置。在本例中,passwd
字段編碼後的數據必定位於actID
後,該值在同一個message中不能重複。對於protobuf而言,標籤1到15的字段在編碼的時候是能夠獲得優化的(標籤值和類型信息只佔一個byte,標籤範圍16到2047佔兩個byte),protobuf可支持的字段數量是$2^{29}-1$。所以,應該將repeated類型的字段標籤未與1~15,節省編碼後的字節數量。enum UserStatus{ OFFLINE=0; ONLINE=1; } message UserInfo{ required int64 actID=1; required string name=2; required UserStatus=3; }
關鍵說明:c++
enum
是枚舉類型的關鍵字,等同於java裏面的enum
UserStatus
爲枚舉的名字;
而不是逗號,
OFFLINE
和ONLINE
表示枚舉值0
和1
表示枚舉所對應的實際整型值,可爲任意整型值,無需從0開始。enum UserStatus{ OFFLINE=0; ONLINE=1; } message UserInfo{ required int64 actID=1; required string name=2; required UserStatus=3; } message LogonRespMessage{ required LoginResult logonResult = 1; required UserInfo userInfo = 2; }
關鍵說明:編程
LogonRespMessage
消息定義中包含另一個消息類型做爲其字段,如UserInfo userInfo
;.proto
文件中,那麼怎麼包含其餘proto文件中的message呢?ProtoBuf提供關鍵字import
將其餘proto文件的message引入到當前proto文件中。例如Import "myproject/CommonMessages.proto"
required
類型的字段。optional
類型的字段。repeated
表示的字段能夠包含0個或多個數據,有別於java的數組,由於java數組中至少包含一個元素。optional
或者repeated
類型的。.proto Type | Notes | C++ Type | Java Type |
---|---|---|---|
double | double | double | |
float | float | float | |
int32 | "Uses variable-length encoding. Inefficient for encoding negative numbers ¨C if your field is likely to have negative values use sint32 instead." | int32 | int |
int64 | "Uses variable-length encoding. Inefficient for encoding negative numbers ¨C if your field is likely to have negative values use sint64 instead." | int64 | long |
uint32 | Uses variable-length encoding. | uint32 | int |
uint64 | Uses variable-length encoding. | uint64 | long |
sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int |
sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long |
fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 228. | uint32 | int |
fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 256. | uint64 | long |
sfixed32 | Always four bytes. | int32 | int |
sfixed64 | Always eight bytes. | int64 | long |
bool | bool | boolean | |
string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String |
bytes | May contain any arbitrary sequence of bytes. | string | ByteString |
optional
或者repeated
限定符,不然沒法保證新老程序在互傳消息的時候消息的兼容性。required
字段,optional
和repeated
類型字段能夠移除,可是他們以前使用的標籤不能使用了。int32
,uint32
,int64
,uint64
和bool
等類型之間是兼容的,sint32
和sint64
是兼容的,stirng
和byte
是兼容的,fixed32
和sfixed32
是兼容的,fixed64
和sfixed64
是兼容的,若是想修改原有字段類型,爲了保證兼容性,只能將其修改成原有類型兼容的類型,不然打破新老消息格式的兼容性。optional
和repeated
限定符是相互兼容的。能夠在.proto
文件中定義包名,如:package abc.lypgone
,該包名生成c++時,替換成名字空間,而java爲java的包名。數組
protobuf 在.proto
文件中定義一些經常使用的選項,這樣protobuf能夠幫助咱們生成更匹配的目標語言代碼。網絡
protobuf的內置選項分爲三個等級:工具
經常使用的protobuf選項有:佈局
java_package
是文件級的選項,指定讓生成的java代碼的包名爲該選項的值;與此同時,輸出的文件也自動輸出到對應包目錄下(上例的com/companyname/projectname
目錄下),該選項對C++沒有影響。java_outer_classname
是文件級別的選項,指定生成的java代碼的外部類名稱。若是沒有指定,java代碼的外部類名稱爲當前文件的文件名部分,同時將文件名轉爲駝峯格式,如my_project.proto
,那麼該文件的外部類名爲MyProject
,該選項對C++代碼無影響。注意,因爲一個java文件只能有一個外部類或者外部接口,因此
.proto
文件中的message
定義的消息均爲外部類的內部類,這樣才能將這些消息定義到一個文件中。c++沒有此限制。性能
SPEED
:表示生成的代碼運行效率高,可是由今生成的代碼編譯後會佔用更多的空間。CODE_SIZE
: 和SPEED偏偏相反,代碼運行效率較低
,可是由今生成的代碼編譯後會佔用更少的空間,一般用於資源有限的平臺,如Mobile。LITE_RUNTIME
: 生成的代碼執行效率高,同時生成代碼編譯後的所佔用的空間也是很是少。這是以犧牲Protocol Buffer提供的反射功能爲代價的。所以咱們在C++中連接Protocol Buffer庫時僅需連接libprotobuf-lite,而非libprotobuf。在Java中僅需包含protobuf-java-2.4.1-lite.jar,而非protobuf-java-2.4.1.jar對於
LITE_MESSAGE
選項而言,其生成的代碼均將繼承自MessageLite
,而非Message
。優化
[pack = true]
: 由於歷史緣由,對於數值型的repeated字段,如int3二、int64等,在編碼時並無獲得很好的優化,然而在新近版本的Protocol Buffer中,可經過添加[pack=true]的字段選項,以通知Protocol Buffer在爲該類型的消息對象編碼時更加高效。如:repeated int32 samples = 4 [packed=true]
。注:該選項僅適用於2.3.0以上的Protocol Buffer
[default = default_value]
: optional類型的字段,若是在序列化時沒有被設置,或者是老版本的消息中根本不存在該字段,那麼在反序列化該類型的消息是,optional的字段將被賦予類型相關的缺省值,如bool被設置爲false,int32被設置爲0。Protocol Buffer也支持自定義的缺省值,如:optional int32 result_per_page = 3 [default = 10]。
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
這裏將給出上述命令的參數解釋。
protoc
爲Protocol Buffer提供的命令行編譯工具。--proto_path
等同於-I
選項,主要用於指定待編譯的.proto消息定義文件所在的目錄,該選項能夠被同時指定多個。--cpp_out
選項表示生成C++代碼,--java_out
表示生成Java代碼,--python_out
則表示生成Python代碼,其後的目錄爲生成後的代碼所存放的目錄。path/to/file.proto
表示待編譯的消息定義文件。注:對於C++而言,經過Protocol Buffer編譯工具,能夠將每一個.proto文件生成出一對.h和.cc的C++代碼文件。生成後的文件能夠直接加載到應用程序所在的工程項目中。如:MyMessage.proto生成的文件爲MyMessage.pb.h和MyMessage.pb.cc。