接口主要遵循 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; }
服務器和客戶端均使用C#語言開發,主要是考慮到Net集成的網絡框架使用起來比較方面,作實例工程比較快;ruby
google protobuf官方的第三方支持庫下載protobuf的NET版本服務器
具體工程文件能夠今後下載: http://download.csdn.net/detail/chenxiaohong3905/7654087網絡
通訊模式採用TCP,在protobuf的二進制基礎上追加了 4個字節的包頭,用於表示protobuf 二進制數據的長度(不包含4字節自身)session
普通的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,須要手動解析;
此流程非必須,只不過爲抓包而演示
GoogleProtocolBuffer , Length 59 描述了 Message 消息二進制的總長度
簡單的推送服務器的全部已經登陸的用戶,包含當前用戶
當用戶登陸或者註銷時經過其它用戶
只演示發送廣播消息,全部用戶都會接收到包含本身