個人Protobuf消息設計原則(續)--實踐

1.首先爲 聊天服務器(Chat)定義google protobuf的協議接口文件

接口主要遵循 Request、Response、Notification(Indication),Command(本文未出現)四大消息分類,而且使用Message頂層消息把Request、Response,Notification等包含起來;並定義一個MSG枚舉值,用於表示具體的消息值(在google protobuf RPC過程當中,其實 每一個service方法就是一個Request和Response的應答對,只不過其消息值的編碼是RPC自動分配的)shell

package chat; //定義protobuf的包名稱空間,對應C++,C#的nanmespace,Java的package
enum MSG
{
 Login_Request  = 10001;
 Login_Response  = 10002;
 Logout_Request  = 10003;
 Logout_Response  = 10004;
 Keepalive_Request = 10005;
 Keepalive_Response = 10006;
 Get_Friends_Request = 10007;
 Get_Friends_Response = 10008;
 Send_Message_Request = 10009;
 Send_Message_Response = 10010;
 Friend_Notification = 20001;
 Message_Notification = 20002;
 Welcome_Notification = 20003;
}
/*下面定義具體的消息內容,MSG枚舉中的每一個消息ID,若是有消息體,則會對應一個message 定義,若是無消息體則沒必要要*/ 
/*Login_Request 消息ID對應的消息名稱爲LoginRequest ; 規則爲取掉下劃線,有利於某些自動化編碼工具編寫自動化代碼*/ 
message LoginRequest
{
 required bytes username = 1;
 optional string password = 2;
}
message LoginResponse
{
 required fixed32 ttl = 1;
}
/*沒有對應的MSG id,則爲其它 消息的字段,做爲子消息,能夠消息嵌套定義,也能夠放在外面,我的習慣放在外部。*/ 
message Friend
{
 required bytes name  = 1;
 optional bool  online = 2;
}
message GetFriendsResponse
{
 repeated Friend  friends  = 1;
}
message SendMessageRequest
{
 optional bytes receiver = 1;
 required bytes  text  = 2;
}
message FriendNotification
{
 required bytes name  = 1;
 optional bool online = 2;
}
message MessageNotification
{
 required bytes sender = 1;
 required bytes text = 2;
 required string timestamp = 3;
}
message WelcomeNotification
{
 required  bytes text = 1;
}
/*請求消息集合,把全部的 XxxxxRequest消息所有集合在一塊兒,使用起來相似於C語言的聯合體,所有使用optional字段,任什麼時候刻根據MSG 的id值,最多隻有一個有效性, 從程序的邏輯上去保證,編譯器(無論是protoc仍是具體語言的編譯器都沒法保證)*/ 
message Request
{
 optional LoginRequest login = 1;
 optional SendMessageRequest send_message = 2;
}
/*與Request做用相同,把全部的XxxxResponse消息集合在一塊兒,看成聯合體使用,不過額外多了幾個字段用於表示應答的結果*/ 
message Response
{
 required bool result = 1;  //true表示應答成功,false表示應答失敗
 required bool last_response = 2;// 一個請求能夠包含多個應答,用於指示是否爲最後一個應答
 optional bytes error_describe = 3;// result == false時,用於描述錯誤信息
 optional LoginResponse login = 4;
 optional GetFriendsResponse get_friends = 5;
}
/*與Request相同,把全部的XxxxxNotification消息集合在一塊兒看成聯合體使用.*/ 
message Notification 
{
 optional FriendNotification friend = 1;
 optional MessageNotification msg = 2;
 optional WelcomeNotification welcome = 3;
}
/*頂層消息,包含全部的Request,Response,Notification,具體包含哪一個消息又 MSG msg_type字段決定,程序邏輯去保證msg_type和具體的消息進行匹配*/ 
message Message 
{
 required MSG  msg_type = 1;
 required fixed32 sequence = 2;//消息系列號,主要用於Request和Response,Response的值必須和Request相同,使得發送端能夠進行事務匹配處理
 optional fixed32 session_id = 3;
 optional Request request  = 4;
 optional Response response = 5;
 optional Notification notification = 6;
}

2.工程實例

服務器和客戶端均使用C#語言開發,主要是考慮到Net集成的網絡框架使用起來比較方面,作實例工程比較快;ruby

google protobuf官方的第三方支持庫下載protobuf的NET版本服務器

具體工程文件能夠今後下載: http://download.csdn.net/detail/chenxiaohong3905/7654087網絡

通訊模式採用TCP,在protobuf的二進制基礎上追加了 4個字節的包頭,用於表示protobuf 二進制數據的長度(不包含4字節自身)session

3. wireshard 抓包分析

普通的wireshark版本是不支持protobuf抓包解析的,能夠下載http://download.csdn.net/detail/chenxiaohong3905/7244655 版本(須要10 CSDN積分,後面要取消,沒法取消積分,上傳新的文件也沒資格了)框架

安裝完下載的版本後須要對齊進行配置 在wireshark安裝目錄下有個protobuf的文件夾用於存放全部 要解析的protobuf文件和配置;工具

注意事項: 每個端口只能對應一個頂層消息 ,至於爲什麼每一個端口只能有一個頂層消息能夠去cnblog參考陳碩的文章,裏面關於protobuf的描述已經解釋了這個問題; protobuf 文件能夠包含其它protobuf接口文件,會自動加載,配置的時候只須要指定頂層消息所在的proto文件便可;ui

裏面vcs.conf是一個配置實例google

對於 聊天服務器的配置能夠以下:編碼

把 protocol.proto文件複製爲 wireshark/protobuf文件夾下面,並穿件一個 文件 protocol.conf 輸入一下內容便可

# same config file for parsing Message messages

name                  = Message

proto_file            = protocol.proto

port                  = 39999

  name 爲頂層消息的名稱, port爲源或目標的端口之一,無論是TCP,UDP都會嘗試解析;若是port端口有其它協議優先註冊了,則沒法解析爲protobuf,須要手動解析;

3.1 鏈接創建 , 服務器推送 Welcome_Notification消息到客戶端

  此流程非必須,只不過爲抓包而演示

GoogleProtocolBuffer , Length 59 描述了 Message 消息二進制的總長度

3.2 登陸聊天服務器

3.3. 獲取朋友列表

 簡單的推送服務器的全部已經登陸的用戶,包含當前用戶

3.4 用戶通知

 當用戶登陸或者註銷時經過其它用戶

3.5 發送消息與消息推送

只演示發送廣播消息,全部用戶都會接收到包含本身

3.6 註銷

相關文章
相關標籤/搜索