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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

protobuf message定义_ProtoBuf 协议设计与开发

發(fā)布時間:2025/3/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 protobuf message定义_ProtoBuf 协议设计与开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?????周日本來要去爬山的,但是沒去成,突然想寫點東西,但本人文采不好,只能閑扯一點技術(shù)方面的文章,整理了下有道筆記,然后最近一直在開發(fā)protobuf的協(xié)議接口,就寫寫ProtoBuf相關(guān)的東西吧。

本文精髓:

  • ? ?protobuf的消息設(shè)計

  • ? ?消息分發(fā)設(shè)計Message Dispatch

  • ? ?針對程序升級的proto設(shè)計

  • 文章末尾對著三點做詳細說明。

    ?????最近一段時間在寫linux服務(wù)端接口程序,剛開始如果按照需求的話,大概有十個接口左右,但是后面慢慢分解需求后,其實真正就只有五個接口。

    ????編碼工作早早完成,進入到測試階段,一般情況可能會等web實現(xiàn)完成后,然后借助web client,在做調(diào)試,但是這期間工作效率不高,而且存在很多問題,可能后臺接口沒實現(xiàn)好,也有可能web沒實現(xiàn)好。作為linux后臺服務(wù)開發(fā),需要會模擬客戶單發(fā)送數(shù)據(jù),如果接口很簡單的話,可以直接使用telnet工具。

    ????現(xiàn)在最為流行的后臺服務(wù)端通信的協(xié)議有:JSON、XML、ProtoBuf,當協(xié)議為這三種的時候,簡單的telnet就不能勝任了,使用JSON和ProtoBuf的話,先借助工具做序列化工作,使用XML的話,也要事先編寫好XML。

    ????為了更加高效的對后臺服務(wù)接口做好單元測試,也為了在web開發(fā)調(diào)試的時候,提供穩(wěn)定的后臺服務(wù)接口,自己利用MFC寫了一個小的調(diào)試工具

    ??

    ????參數(shù)設(shè)置里面輸入的是json串,因為這個有很多工具方便序列化,如:https://www.bejson.com/jsoneditoronline/

    ????這個工具很簡單,從界面就三個輸入,IP、port、消息類型,主要工作就是模擬客戶端向服務(wù)端發(fā)送消息:

    ????????需要借用服務(wù)端的proto協(xié)議文件

    ????????序列化protobuf

    ????????根據(jù)消息類型做消息分發(fā)

    ????這里用到protobuf,先大概說一下它的使用與原理

    ????1,介紹安裝

    ????????直接去百度,這里就跳過

    ????2,編寫 .proto文件

    ????????來個例子:

    ????????package lm;

    ????????message helloworld

    ????????{

    ????????required int32 ? ? id = 1; ?// ID

    ????????required string ? ?str = 2; ?// str

    ????????optional int32 ? ? opt = 3; ?//optional field

    ????????}

    ????限定修飾符 + 數(shù)據(jù)類型 + 字段名稱 = 字段編碼值

    ????盡量養(yǎng)成良好測編程習(xí)慣,對proto文件命名與消息名做規(guī)范的命名

    ????在上例中,package 名字叫做 lm,定義了一個消息 helloworld,該消息有三個成員,類型為 int32 的 id,另一個為類型為 string 的成員 str。opt 是一個可選的成員,即消息中可以不包含該成員。

    ????3,編譯.proto文件

    ????寫好 proto 文件之后就可以用 Protobuf 編譯器將該文件編譯成目標語言了。本例中我們將使用 C++。假設(shè)您的 proto 文件存放在 $SRC_DIR 下面,您也想把生成的文件放在同一個目錄下,則可以使用如下命令:

    protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

    命令將生成兩個文件:

    ????????lm.helloworld.pb.h , 定義了 C++ 類的頭文件

    ????????lm.helloworld.pb.cc , C++ 類的實現(xiàn)文件

    ????在生成的頭文件中,定義了一個 C++ 類 helloworld

    ????4,序列化

    ????在第三部編譯生成的cc文件中,有一系列的SerializeToXXX方法,如SerializeToArray,可以根據(jù)具體情況用這一系列方法進行序列化。

    ????5,反序列化

    ????在第3個步驟編譯生成的cc文件中,有一系列的ParseFromXXX方法,如ParseFromArray,可以根據(jù)具體情況用這一系列方法進行反序列化。

    ????掌握以上幾個步驟基本就能搞定proto的開發(fā)了,進階的話可以去掌握proto的數(shù)據(jù)類型以及requried、optional、repeated限定修飾符,和message的嵌套(message嵌套可以設(shè)計出更多復(fù)雜的協(xié)議,滿足更復(fù)雜的需求)。

    ??? protobuf的優(yōu)劣自己去百度,JSON,XML我也有用過,但是相對來說,谷歌的protobuf是我用起來最方便高效的。

    ????這是網(wǎng)上的一個測試結(jié)果:http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

    ????回到文章開頭部分說的精髓,現(xiàn)在逐一到來

    ????一,proto的設(shè)計:

    ????一般設(shè)計規(guī)則如下

    ????message Request

    ????{

    ????required fixed64 msgtype = 1;

    ????required bytes bodys = 2;

    ????}

    ????一個消息類型加一個消息體,但這不能滿足復(fù)雜的業(yè)務(wù)需求,所以復(fù)雜的系統(tǒng)里面一般拆成這樣:

    ????message Header

    ????{

    ????required fixed64 msgtype = 1;

    ????}

    ????message HelloworldRequest

    ????{

    ????required int32 ? ? id = 1; ?// ID

    ????required string ? ?str = 2; ?// str

    ????optional int32 ? ? opt = 3; ?//optional field

    ????}

    ????一個消息類型(單獨定義一個文件)對應(yīng)一個請求消息,一個請求消息對應(yīng)一個接口,消息里面的字段對應(yīng)接口所需要的參數(shù),這是常用的設(shè)計方法,能滿足所有的業(yè)務(wù)需求。

    ????二,消息分發(fā)的設(shè)計

    這里的message dispatch是指程序根據(jù)不同的msgtype,反序列化proto和做不同的業(yè)務(wù)邏輯處理。

    ????古老而又傳統(tǒng)的設(shè)計是采用switch case來做(我曾經(jīng)看到有在用if else的),這種方法有很多不足之處,我這里舉幾個很常見的:

    ????1,代碼臃腫,隨著消息類型的增加,會有n多的case

    ??? 2,假設(shè)case里漏掉了break;那就不妙了。

    ??? 3,代碼維護差,每次增加msgtype,除了實現(xiàn)對應(yīng)的業(yè)務(wù)邏輯處理,還要到消息入口增加對應(yīng)的case。

    ????在c語言里面,有一種很實用的辦法,那就是函數(shù)指針,很多開源的和上層應(yīng)用的回調(diào)函數(shù)或方法的底層都是封裝了c語言的函數(shù)指針,這里提到函數(shù)指針,我簡單介紹一下(本文沒有用很大篇幅來說明函數(shù)指針,掌握其基本定義,慢慢學(xué)會衍生到復(fù)雜的概念):

    ????????從概念上說,函數(shù)指針是指向函數(shù)的指針變量,它本質(zhì)上是一個指針變量。

    ????????其廣泛的定義是:int (*f) (int x);

    ????????復(fù)制和調(diào)用:int func(int x); ? f = func;

    ????那么函數(shù)指針在Message Dispath 如何設(shè)計呢,還是來一個簡單的例子:

    ????定義一個結(jié)構(gòu)體

    ????????struct SMsgCmd {

    ????????int msgtype; ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*msg type*/

    ????????int (*func)(const char *argv); ? ? ? ? ? /* handler * 函數(shù)指針/

    ????????};

    ????定義一個結(jié)構(gòu)體數(shù)組,并初始化

    ????????static struct SMsgCmd commands[] = {

    ????????{ 1, ? Request1},

    ????????{ 2, ? Request1},

    ????????};

    ????在服務(wù)程序的消息入口處,遍歷改數(shù)組即可

    ????????for ()

    ????????{

    ????????if (msgtype == commands[i].msgtype){

    ????????(*commands[i].func)(argv);

    ????????}

    ????????}

    ????在c++11里面,可以利用std::functionstd::bind,其原理跟函數(shù)指針一個道理。

    ????三,針對程序升級的proto設(shè)計

    ????程序升級是常有的事,但我們升級的時候需要考慮兼容性,之前有看到過同個版本號如

    ????if (version == 1){

    ????}

    ????else if (version > 2)

    ????.........

    ????這樣做的缺陷我就不在過多的說明了。

    ????對于proto的協(xié)議來說,我們只要做到以下幾點,就會完美兼容新舊版本

    ????????1,不要隨意添加或刪除 required限定詞修飾的字段

    ????????2,不要隨意改變現(xiàn)有字段編碼值

    ????????3,若需要新增字段,請用optional限定詞修飾

    本文到此就算結(jié)束了,若有錯誤之處,請多多指教!

    歡迎關(guān)注本人微信公眾號:lzyTalk江湖,不只是談江湖,還會分享很多技術(shù)干貨哦!

    總結(jié)

    以上是生活随笔為你收集整理的protobuf message定义_ProtoBuf 协议设计与开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。