日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

protobuf 语法浅析

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 protobuf 语法浅析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

Protobuf

為什么用Protobuf Buffer

跨語言平臺編程,使用SOAP的話,該方式是使用xml的方式傳輸,會大大增加網絡的IO,而且xml的解析復雜,降低報文的解析性能。

定義一個Protobuf消息

message LogonReqMessage{required int64 actID=1;required string passwd=2; }

關鍵說明:

  • message是消息的關鍵字
  • LogonReqMessage是消息名字,相當于java的類名
  • required前綴表示該字段未必要字段,序列化前后必須賦值的字段。protobuf還存在兩個類似的關鍵字optional和repeated主要用于表示數組字段。
  • int64和string表示長整型和字符串類型的消息字段,在protobuf中存在一張類型對照表,即protobuf類型與其他語言的類型對照。
  • actID和passwd分別表示消息的字段名,等同于java中的域名變量名。
  • 標簽數字1和2表示不同的字段在序列化前后的二進制中的布局位置。在本例中,passwd字段編碼后的數據一定位于actID后,該值在同一個message中不能重復。對于protobuf而言,標簽1到15的字段在編碼的時候是可以得到優化的(標簽值和類型信息只占一個byte,標簽范圍16到2047占兩個byte),protobuf可支持的字段數量是$2^{29}-1$。因此,應該將repeated類型的字段標簽未與1~15,節省編碼后的字節數量。
  • 定義第二個protobuf消息

    enum UserStatus{OFFLINE=0;ONLINE=1; }message UserInfo{required int64 actID=1;required string name=2;required UserStatus=3; }

    關鍵說明:

  • enum是枚舉類型的關鍵字,等同于java里面的enum
  • UserStatus為枚舉的名字
  • 和java一樣枚舉之間的分隔符是分好;而不是逗號,
  • OFFLINE和ONLINE表示枚舉值
  • 0和1表示枚舉所對應的實際整型值,可為任意整型值,無需從0開始。
  • 定義第三個protobuf消息

    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;
  • 上例的UserInfo和LogonRespMessage被定義在同一個.proto文件中,那么怎么包含其他proto文件中的message呢?ProtoBuf提供關鍵字import將其他proto文件的message引入到當前proto文件中。例如Import "myproject/CommonMessages.proto"
  • 限定符號

  • 每個消息必須有一個字段是required類型的字段。
  • 每個消息包含0個或多個optional類型的字段。
  • repeated表示的字段可以包含0個或多個數據,有別于java的數組,因為java數組中至少包含一個元素
  • 如果打算在原有消息協議中添加新的字段,同時保證老的字段能正常的讀取寫入,那么新添加的字段必須是optional或者repeated類型的。
  • proto類型對照表

    .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

    protobuf消息升級原則

  • 不要修改已經存在字段的標簽號
  • 任何新添加的字段必須是optional或者repeated限定符,否則無法保證新老程序在互傳消息的時候消息的兼容性。
  • 在原有消息中,不能移除已經存在的required字段,optional和repeated類型字段可以移除,但是他們之前使用的標簽不能使用了。
  • int32,uint32,int64,uint64和bool等類型之間是兼容的,sint32和sint64是兼容的,stirng和byte是兼容的,fixed32和sfixed32是兼容的,fixed64和sfixed64是兼容的,如果想修改原有字段類型,為了保證兼容性,只能將其修改為原有類型兼容的類型,否則打破新老消息格式的兼容性。
  • optional和repeated限定符是相互兼容的。
  • packages

    可以在.proto文件中定義包名,如:package abc.lypgone,該包名生成c++時,替換成名字空間,而java為java的包名。

    options

    protobuf 在.proto文件中定義一些常用的選項,這樣protobuf可以幫助我們生成更匹配的目標語言代碼。

    protobuf的內置選項分為三個等級:

  • 文件級,這樣的選項影響當前文件的所有消息和枚舉。
  • 消息級,這樣的選項僅影響某個消息及其包含的所有字段。
  • 字段級,這樣的選項近影響某個字段。
  • 常用的protobuf選項有:

  • option java_package="com.companyname.projectname"; java_package 是文件級的選項,指定讓生成的java代碼的包名為該選項的值;與此同時,輸出的文件也自動輸出到對應包目錄下(上例的com/companyname/projectname目錄下),該選項對C++沒有影響。
  • option java_outer_classname="LYPhoneMessage"; java_outer_classname是文件級別的選項,指定生成的java代碼的外部類名稱。如果沒有指定,java代碼的外部類名稱為當前文件的文件名部分,同時將文件名轉為駝峰格式,如my_project.proto,那么該文件的外部類名為MyProject,該選項對C++代碼無影響。
  • 注意,由于一個java文件只能有一個外部類或者外部接口,所以.proto文件中的message定義的消息均為外部類的內部類,這樣才能將這些消息定義到一個文件中。c++沒有此限制。

  • option optimize_for = LITE_RUNTIME; optimize_for 是文件級選項,是protobuf優化選項。該選項又分為3個等級:
  • 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字段,如int32、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。

    轉載于:https://my.oschina.net/hgfdoing/blog/712889

    總結

    以上是生活随笔為你收集整理的protobuf 语法浅析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。