隋心怡,王瑞剛,梁小江
(1.西安郵電大學(xué) 物聯(lián)網(wǎng)與兩化融合研究院,陜西 西安 710061;2.陜西省信息化工程研究院,陜西 西安 710061)
基于Google Protocol Buffer的即時(shí)通訊系統(tǒng)設(shè)計(jì)
隋心怡1,王瑞剛1,梁小江2
(1.西安郵電大學(xué) 物聯(lián)網(wǎng)與兩化融合研究院,陜西 西安 710061;2.陜西省信息化工程研究院,陜西 西安 710061)
為提高即時(shí)通訊服務(wù)數(shù)據(jù)傳輸和存儲(chǔ)的高效性和穩(wěn)定性,提出了一種基于Google Protocol Buffer的即時(shí)通訊系統(tǒng)。該系統(tǒng)利用Protocol Buffer數(shù)據(jù)交換格式對(duì)通訊數(shù)據(jù)進(jìn)行處理,提高系統(tǒng)的傳輸效率。實(shí)驗(yàn)結(jié)果表明,與json、xml相比,經(jīng)Protocol Buffer序列化后的數(shù)據(jù)大小要明顯小于其他兩種方法,系統(tǒng)整體傳輸效率和安全性較高,并且具有良好的擴(kuò)展性。
即時(shí)通訊;Protocol Buffer;序列化;數(shù)據(jù)交換格式;數(shù)據(jù)傳輸
即時(shí)通訊(Instant Message,IM)是一種可以讓使用者在局域網(wǎng)或互聯(lián)網(wǎng)上建立某種私人聊天的實(shí)時(shí)通訊服務(wù)。由于其靈活性和方便性,被越來(lái)越多地應(yīng)用到日常生活中。即時(shí)通訊也對(duì)通信的穩(wěn)定性提出了更高的要求[1-3]。在即時(shí)通訊中,大量數(shù)據(jù)在移動(dòng)端和服務(wù)端進(jìn)行頻繁的交互都是需要建立在一定的數(shù)據(jù)交換格式基礎(chǔ)上,以保證發(fā)送方和接收方能夠按照約定的方式傳輸數(shù)據(jù)[4-7]。
Google提出的Protocol Buffer是一種基于二進(jìn)制的數(shù)據(jù)傳輸格式,在數(shù)據(jù)傳輸過(guò)程中可以高效地壓縮數(shù)據(jù),不僅使數(shù)據(jù)傳輸量減少,同時(shí)也加快了數(shù)據(jù)的壓縮速率,從而進(jìn)一步提高數(shù)據(jù)傳輸?shù)男屎晚憫?yīng)速度[8-11]。
1.1 簡(jiǎn)介
Protocol Buffer是Google公司開(kāi)發(fā)的一種混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn),主要應(yīng)用在結(jié)構(gòu)化數(shù)據(jù)的描述、傳輸和存儲(chǔ)幾個(gè)方面。Protobuf(Protocol Buffer)將數(shù)據(jù)結(jié)構(gòu)對(duì)象轉(zhuǎn)換成二進(jìn)制數(shù)據(jù)流的形式進(jìn)行存儲(chǔ),可以簡(jiǎn)單的實(shí)現(xiàn)數(shù)據(jù)流與對(duì)象之間的轉(zhuǎn)換[12-13]。
開(kāi)發(fā)人員按照一定的語(yǔ)法定義結(jié)構(gòu)化的消息格式,然后發(fā)送給命令行工具生成相關(guān)的類(lèi),以支持Java、C++、Python等語(yǔ)言環(huán)境。將這些生成類(lèi)引入到系統(tǒng)項(xiàng)目中,整個(gè)系統(tǒng)可以直接調(diào)用相關(guān)方法完成業(yè)務(wù)消息的序列化和反序列化[14-15]。
1.2 應(yīng)用場(chǎng)景
Protobuf作為一種兼容性較好、高效率的二進(jìn)制數(shù)據(jù)傳輸格式,多用于分布式應(yīng)用之間的數(shù)據(jù)通信或異構(gòu)環(huán)境下的數(shù)據(jù)交換,包括網(wǎng)絡(luò)傳輸、數(shù)據(jù)存儲(chǔ)、配置文件等領(lǐng)域。
在實(shí)際開(kāi)發(fā)中,不同語(yǔ)言的前后端在交互時(shí)不可直接調(diào)用。為保證通訊的即時(shí)性,服務(wù)端隨時(shí)可能下發(fā)數(shù)據(jù)到客戶(hù)端,客戶(hù)端同時(shí)主動(dòng)向服務(wù)端發(fā)送請(qǐng)求。這種交互的實(shí)現(xiàn)要求必須基于確定的協(xié)議來(lái)規(guī)定數(shù)據(jù)格式,也就是說(shuō),在服務(wù)器與客戶(hù)端交互時(shí),需要將準(zhǔn)備傳輸?shù)膬?nèi)容按照規(guī)定模式轉(zhuǎn)化為一種中間語(yǔ)言(Byte數(shù)組),然后在另一端根據(jù)同樣的格式轉(zhuǎn)換回原來(lái)語(yǔ)言的對(duì)象。開(kāi)發(fā)者使用Protobuf作為數(shù)據(jù)交換格式,可以方便地定義業(yè)務(wù)傳輸協(xié)議,高效、簡(jiǎn)單地完成數(shù)據(jù)交換。通過(guò)Protobuf在開(kāi)發(fā)時(shí)不再需要關(guān)注通信協(xié)議中的編碼解碼工作,而更多的專(zhuān)注于業(yè)務(wù)處理上。
1.3 編碼設(shè)計(jì)
Protobuf在功能上與xml類(lèi)似,但是經(jīng)過(guò)序列化后的數(shù)據(jù)更小,所以解析數(shù)據(jù)速率更快。其序列化后的Byte數(shù)組簡(jiǎn)潔緊湊,編解碼速度快,而且占用的空間也少。與xml相比,Protocol序列化之后的數(shù)據(jù)量約為xml的1/3~1/10。
整個(gè)消息以二進(jìn)制流的方式存儲(chǔ),在這個(gè)二進(jìn)制流中,逐個(gè)字段以定義的順序緊緊相鄰,每個(gè)字段中由元信息tag和字段的值value組成。圖1所示為序列化編碼示意圖。
圖1 Protocol Buffer序列化編碼示意圖
解碼程序讀入二進(jìn)制的字節(jié)流進(jìn)行解碼時(shí),通過(guò)引用消息的類(lèi)型定義決定解析的字段名字和聲明類(lèi)型。
1.4 實(shí)現(xiàn)過(guò)程
Protobuf采用二進(jìn)制形式對(duì)數(shù)據(jù)進(jìn)行描述,編程人員只需要使用其描述一次數(shù)據(jù)結(jié)構(gòu),便可以滿(mǎn)足跨平臺(tái)的、不同語(yǔ)言之間的結(jié)構(gòu)化的讀寫(xiě)。
實(shí)現(xiàn)過(guò)程如下:
(1) 編寫(xiě)協(xié)議文件.proto,在協(xié)議文件中定義需要做串行化的數(shù)據(jù)結(jié)構(gòu)信息。定義的每個(gè)文件都屬于一個(gè)面向?qū)ο蟮募?,集合中先?xiě)入數(shù)據(jù)類(lèi)型再寫(xiě)Protobuf數(shù)據(jù),其中包含著消息體的各種屬性和邏輯關(guān)系;
(2) 通過(guò)protoc編譯器的命令行生成所選擇語(yǔ)言的特定類(lèi)。生成的代碼中定義了操作消息屬性的各個(gè)方法,根據(jù)屬性的不同生成包括set()、get()等函數(shù),且每個(gè)生成的類(lèi)里都會(huì)有序列化和反序列化的方法,這些方法用于轉(zhuǎn)化當(dāng)前數(shù)據(jù)為流數(shù)據(jù)發(fā)送或從流數(shù)據(jù)解析數(shù)據(jù);
(3) 服務(wù)端和客戶(hù)端分別調(diào)用生成類(lèi)。此處同調(diào)用普通的類(lèi)庫(kù)一樣,通過(guò)message接口提供的ParseFrom()方法從輸入流中讀取二進(jìn)制的編碼消息再解釋成message對(duì)象便可以直接操作。
2.1 即時(shí)通訊概況
即時(shí)通訊系統(tǒng)一般分為客戶(hù)端和服務(wù)器端,采用典型的分布式客戶(hù)/服務(wù)器結(jié)構(gòu),服務(wù)器提供消息服務(wù),客戶(hù)端是用戶(hù)代理,之間通過(guò)一定的協(xié)議進(jìn)行交互。要使用戶(hù)可以在Android、iOS平臺(tái)下進(jìn)行文本消息、文件等形式的即時(shí)通訊功能,總體需求架構(gòu)如圖2所示。
圖2 即時(shí)通訊需求架構(gòu)
根據(jù)系統(tǒng)架構(gòu)及功能需求,包括用戶(hù)登錄、消息傳輸?shù)人薪换サ恼?qǐng)求及回應(yīng)都有相應(yīng)的消息格式。Protocol Buffer應(yīng)用于即時(shí)通訊系統(tǒng)中,需要先構(gòu)建對(duì)應(yīng).proto的消息數(shù)據(jù)文件,通過(guò)編譯器編譯后生成對(duì)應(yīng)的所需語(yǔ)言的數(shù)據(jù)類(lèi)和接口。
2.2 Protocol Buffer定義及通信格式設(shè)計(jì)
整個(gè)系統(tǒng)定義一個(gè)枚舉消息,其中包含系統(tǒng)所用到的所有模塊的消息序號(hào)
enum Modle{
logininfo = 1; //用戶(hù)登錄信息
login_res = 2; //用戶(hù)登錄響應(yīng)
msginfo = 3; //消息傳送信息
msg_res = 4; //消息傳送響應(yīng)
fileinfo = 5; //文件傳輸信息
file_res = 6; //文件傳輸響應(yīng)
… …
}
在整個(gè)即時(shí)通訊系統(tǒng)中,包括用戶(hù)登陸、消息傳送等每個(gè)服務(wù)模塊都是和請(qǐng)求應(yīng)答相對(duì)應(yīng)的,同時(shí)為每一個(gè)具有消息體的消息定義一個(gè)對(duì)應(yīng)的Protobuf message,以用戶(hù)登錄為例構(gòu)建login.proto文件,其中登錄請(qǐng)求logininfo消息結(jié)構(gòu)化定義具體如下
message logininfo{
required string login_name = 1;
required string passwd = 2;
enum UserStat{
online = 1;
leave = 2;
}
optional UserStat type = 3[default = online];
optional int32 version = 4;
}
logininfo消息包含的login_name、passwd、type、version字段分別表示用戶(hù)登錄時(shí)的用戶(hù)名、密碼、登錄狀態(tài)以及客戶(hù)端版本。其中required修飾的字段表示登錄名、密碼這些信息是必不可少的;定義UserStat枚舉用戶(hù)不同的登錄狀態(tài),包括用戶(hù)在線(xiàn)和離線(xiàn)狀態(tài),也屬于logininfo信息的一部分,同時(shí)要定義type字段調(diào)用枚舉UserStat的值用以表示用戶(hù)登錄的不同狀態(tài),和version一樣用optional修飾表示該字段可選,即用戶(hù)信息中不一定要有用戶(hù)狀態(tài)和客戶(hù)端版本信息。
網(wǎng)絡(luò)傳輸過(guò)程中數(shù)據(jù)需要按照一定的格式組成固定的結(jié)構(gòu)。Protobuf將數(shù)據(jù)進(jìn)行序列化后,使用TCP/IP進(jìn)行網(wǎng)絡(luò)傳輸時(shí),需要對(duì)所有的數(shù)據(jù)傳輸單元做粘包、拆包處理,而傳輸?shù)膍essage并未對(duì)消息長(zhǎng)度做出定義,接收方不能做出相應(yīng)解析。要保證通信的正常進(jìn)行,傳輸數(shù)據(jù)中需要包含除原始數(shù)據(jù)本身之外的數(shù)據(jù)說(shuō)明信息以及與數(shù)據(jù)交換相關(guān)的描述性信息。設(shè)計(jì)固定的通信格式,將序列化后獲得的消息嵌入到另外一個(gè)二進(jìn)制信息中,以確保接收方從傳輸數(shù)據(jù)中提取出相應(yīng)的數(shù)據(jù)進(jìn)行解析。
為便于數(shù)據(jù)的編解碼操作,本文定義一種通信格式,在數(shù)據(jù)發(fā)送之前對(duì)原始數(shù)據(jù)添加消息頭封裝成傳輸數(shù)據(jù)單元。消息頭需要包含包括數(shù)據(jù)長(zhǎng)度、服務(wù)號(hào)在內(nèi)的幾種字段主要設(shè)計(jì)。
圖3 數(shù)據(jù)交換格式
前4位Length 標(biāo)識(shí)出原始數(shù)據(jù)的長(zhǎng)度;Protocol打包的數(shù)據(jù)沒(méi)有自帶長(zhǎng)度而不能直接對(duì)消息進(jìn)行切分,發(fā)送數(shù)據(jù)前計(jì)算發(fā)送數(shù)據(jù)的大小并存儲(chǔ)到前4 Byte空間中,接收數(shù)據(jù)時(shí)解析消息頭可以獲得原始數(shù)據(jù)的大小,取消息頭之后指定大小的數(shù)據(jù)進(jìn)行解析;
Module表示消息類(lèi)型,在消息頭占2 Byte;解碼后根據(jù)Module字段可以知道要處理的消息屬于哪個(gè)模塊,將任務(wù)派發(fā)到相應(yīng)業(yè)務(wù)模塊的處理函數(shù)以完成相應(yīng)的業(yè)務(wù)過(guò)程;
Array 占整個(gè)消息頭的后2 Byte,用以判斷傳輸數(shù)據(jù)的大小端;由于跨平臺(tái)的網(wǎng)絡(luò)數(shù)據(jù)交換需要進(jìn)行字節(jié)序轉(zhuǎn)換,通信雙方需要達(dá)成一致的規(guī)則以保證交流的信息單元是以正確的順序被傳送。
2.3 調(diào)用機(jī)制
對(duì)已經(jīng)定義好的結(jié)構(gòu)化消息通過(guò)Protobuf的編譯器protoc生成特定的類(lèi),命令如下
protoc --java_out=. login.proto
protoc --cpp_out=. login.proto
protoc -python_out=.login.proto
運(yùn)行以上命令在.proto文件所在目錄下生成相應(yīng)的Java、C++和Python的數(shù)據(jù)類(lèi)和接口代碼。Protocol編譯器會(huì)為每一個(gè)message生成一個(gè)類(lèi),其中包含基本函數(shù)、消息實(shí)現(xiàn)、嵌套類(lèi)型、訪問(wèn)器等部分內(nèi)容。
本次實(shí)驗(yàn)調(diào)用生成的C++語(yǔ)言相關(guān)代碼,可以直接在服務(wù)端引用生成文件login.pb.cc和login.pb.h中的類(lèi)。引入生成文件到工程中可以像使用自定義類(lèi)一樣初始化相應(yīng)數(shù)據(jù)類(lèi)型,對(duì)Modlue中每一個(gè)枚舉的消息都會(huì)特化一個(gè)process方法。
客戶(hù)端在與服務(wù)端進(jìn)行數(shù)據(jù)交互之前,網(wǎng)關(guān)要對(duì)消息頭中的字段進(jìn)行初始化,然后調(diào)用Protobuf提供的編碼方法將原始數(shù)據(jù)結(jié)構(gòu)化成二進(jìn)制數(shù)據(jù)流,并將數(shù)據(jù)寫(xiě)入隊(duì)列數(shù)據(jù)結(jié)構(gòu)的請(qǐng)求隊(duì)列中,添加初始化之后的數(shù)據(jù)長(zhǎng)度等字段,封裝成數(shù)據(jù)傳輸單元后發(fā)送至服務(wù)端;服務(wù)端接收后對(duì)其進(jìn)行分包解析,提取消息頭中的說(shuō)明信息后調(diào)用Protobuf的解碼方法反序列化請(qǐng)求包,同時(shí)向客戶(hù)端返回?cái)?shù)據(jù)接收成功的確認(rèn)完成數(shù)據(jù)傳輸過(guò)程。
3.1 提高傳輸效率
Protobuf傳輸數(shù)據(jù)較json、xml速率均有所提升。隨機(jī)測(cè)試一組數(shù)據(jù)經(jīng)程序處理后,得出Protobuf、json和xml序列化之后的數(shù)據(jù)統(tǒng)計(jì)如表1所示。
表1 數(shù)據(jù)結(jié)果統(tǒng)計(jì)
選取中間4組數(shù)據(jù)繪制成折線(xiàn)對(duì)比圖,如圖4所示。
圖4 數(shù)據(jù)折線(xiàn)對(duì)比圖
通過(guò)數(shù)據(jù)對(duì)比測(cè)試可以得出以下結(jié)論:隨著原始數(shù)據(jù)的增加,Protobuf序列化之后的數(shù)據(jù)始終是最小的;在原始數(shù)據(jù)逐步增大時(shí),Protobuf與xml、json比較其優(yōu)勢(shì)也相對(duì)減少。
結(jié)合日常使用情況可以得知,IM軟件的移動(dòng)端用戶(hù)更習(xí)慣于用少于100字(約500 Byte)的文本信息交流,Protocol較json、xml序列化在該條件下優(yōu)勢(shì)較為明顯。故采用Protocol作為即時(shí)通訊系統(tǒng)中的數(shù)據(jù)交換格式可以在大多數(shù)情況下提升系統(tǒng)性能。
3.2 易于擴(kuò)展
在實(shí)際應(yīng)用中,系統(tǒng)功能需要經(jīng)常性升級(jí),可以通過(guò)在.proto文件中增加新的message字段實(shí)現(xiàn)。Protobuf提供了很好的兼容性,不必破壞已部署的、依靠老數(shù)據(jù)格式的程序就可以對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行升級(jí)。
在對(duì)協(xié)議擴(kuò)展時(shí)要求遵守必要的規(guī)則,包括不能修改現(xiàn)有的tag number、不能添加和刪除required字段、添加或刪除optional和repeated字段并使用新的tag number。遵守這些規(guī)則,原代碼可以正確讀取新的message,但會(huì)忽略新的字段;對(duì)于刪除optional的字段,原碼會(huì)使用其默認(rèn)值;對(duì)于刪除的repeated字段,則將其置空。Protobuf良好的向后兼容性可以保證系統(tǒng)功能的正常運(yùn)行。
3.3 安全性
Protobuf對(duì)外部類(lèi)的成員變量?jī)H提供了getter()方法,而沒(méi)有提供set方法為成員變量賦值,對(duì)所有外部類(lèi)的賦值操作都需要通過(guò)builder類(lèi)來(lái)執(zhí)行,賦值完成后將builder類(lèi)成員的值賦給外部類(lèi)的對(duì)應(yīng)對(duì)象。一旦數(shù)據(jù)構(gòu)建完成將不能再對(duì)其進(jìn)行修改,保證了數(shù)據(jù)傳輸?shù)陌踩浴?/p>
通過(guò)引入Google Protocol Buffer的數(shù)據(jù)結(jié)構(gòu)和序
列化方法,設(shè)計(jì)了完整的數(shù)據(jù)傳輸協(xié)議將數(shù)據(jù)結(jié)構(gòu)封裝到數(shù)據(jù)傳輸單元,完成了即時(shí)通訊系統(tǒng)中客戶(hù)端和服務(wù)端的數(shù)據(jù)傳輸過(guò)程。
本文主要根據(jù)對(duì)Protobuf協(xié)議的分析結(jié)果討論即時(shí)通訊系統(tǒng)框架,整體框架仍需要按照實(shí)際需求進(jìn)行繼續(xù)完善。通過(guò)研究測(cè)試,Protobuf的引入確實(shí)給即時(shí)通訊系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)在系統(tǒng)效率及安全性等方面帶來(lái)較大的提高。
[1] 聶曉旭,于鳳芹,欽道理. 基于 Protobuf 的數(shù)據(jù)傳輸協(xié)議[J].計(jì) 算 機(jī) 系 統(tǒng) 應(yīng) 用,2015,24(8):112-116.
[2] 殷昊,沈奇威,王純.Protocol Buffer在Android企業(yè)云通訊錄中的應(yīng)用[J].電信科學(xué),2012(9):148-151.
[3] 李紀(jì)欣,王康,周立發(fā),等.Google Protobuf在Linux Socket通訊中的應(yīng)用[J].電腦開(kāi)發(fā)與應(yīng)用,2013(4):1-5.
[4] 宮唐小恒,李旭偉. Protocol Buffers:比XML快近100倍[J].電腦與信息技術(shù),2009(1):65-68.
[5] 竇進(jìn)葉.基于Protocol Buffers的企業(yè)即時(shí)通訊應(yīng)用的研究和實(shí)現(xiàn)[D].青島:中國(guó)海洋大學(xué),2014.
[6] 李毅成,梁濤. 即時(shí)通訊軟件的協(xié)議設(shè)計(jì)[J]. 辦公自動(dòng)化雜志,2008(143):38-39.
[7] 劉青. 基于 Protocol Buffer 的即時(shí)通信監(jiān)控系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[D].武漢:華中科技大學(xué),2013.
[8] Google.Protocol buffers[EB/OL]. (2008- 07- 09)[2015-12-12]http://code.google.com/apis/pro Toc Olbuffers/docs/overview.html.
[9] Google. Protobuf for developers[EB/OL].(2010-03-02)[2015-12-10] https://developers.google.com/protocol-buffers/docs/overview.
[10] Feng Jianhua. Google protocol buffers research and application in online game[J]. IEEE Network, 2011, 7(11):625-627.
[11] 黎二榮.移動(dòng)云計(jì)算環(huán)境下即時(shí)通訊框架的研究與實(shí)現(xiàn)[D].北京:中國(guó)地質(zhì)大學(xué),2014.
[12] 宋瑾.基于ProtocolBuffer 協(xié)議的服務(wù)端-客戶(hù)端通信[J].電腦編程技巧與維護(hù),2014,12(47):100-101.
[13] 史棟杰.五種快速序列化框架的性能比較[J].電腦知識(shí)與技術(shù),2010,11(34):9710-9712.
[14] 王少林,李祥明,李永剛.基于 Protocol Buffers 的航天測(cè)控?cái)?shù)據(jù)交換模式研究[J].遙測(cè)遙控,2012, 6(33):55-60.
[15] 朱浩悅,侯敏.基于Android的移動(dòng)即時(shí)通訊系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J].電腦知識(shí)與技術(shù),2015, 11(34):106-107.
A Design of Instant Message System based on Google Protocol Buffer
SUI Xinyi1,WANG Ruigang1,LIANG Xiaojiang2
(1. Institute of IOT&IT-based Industrialization,Xi’an University of Posts and Telecommunications,Xi’an 710061,China ;2. Institute of Communication Technology, Xi’an 710061,China)
In view of improving the efficiency and stability of the data transmission and storage in instant messaging service,an instant messaging system based on Google Protocol Buffer is proposed.This pager put Protocol buffers data-exchange format in processing communication data,increasing the efficiency of data transmission.Experimental results show that the data size after Buffer Protocol serialization is significantly less than JSON or XML.Transmission efficiency and security is relatively high and has a good expansibility.
instant messaging;Protocol Buffer;serialize;data-exchange format;data transmission
2016- 03- 25
隋心怡(1992-),女,碩士研究生。研究方向:移動(dòng)互聯(lián)網(wǎng)。王瑞剛(1966-),男,高級(jí)工程師。研究方向:多媒體通信領(lǐng)域。梁小江(1983-),男,工程師。研究方向:云計(jì)算與大數(shù)據(jù)處理。
10.16180/j.cnki.issn1007-7820.2017.01.033
TN919.6;TP302.1
A
1007-7820(2017)01-119-04