1. 程式人生 > >client: c#+protobuf, server: golang+protobuf

client: c#+protobuf, server: golang+protobuf

前段時間看到一篇博文《[可在廣域網部署執行的即時通訊系統 -- GGTalk總覽(附原始碼下載)](https://www.cnblogs.com/justnow/p/3382160.html)》,他是用C#實現的即時通訊系統,功能強大,介面漂亮。 就想用golang重寫服務端,把程式碼下載回來,發現通訊框架用的是ESFramework,我沒用過也不知道ESFramework的協議,重寫是不行的了,只能把原作者的客戶端介面扣出來,自己寫一個,客戶端是C#+protobuf, 服務端是golang+protobuf,動起手來才發現,功能細節實在太多了,沒精力搞下去了,就權當protobuf的學習例子吧。 **一、協議** ``` 4個位元組的長度 + 4個位元組的包長 + protobuf資料包 // 登入的請求和響應 LoginRequestCMD uint32 = 1 LoginResponseCMD uint32 = 2 // 註冊使用者的請求和響應 RegisterRequestCMD uint32 = 3 RegisterResponseCMD uint32 = 4 // 獲取朋友列表的請求和響應 GetFriendsRequestCMD uint32 = 5 GetFriendsResponseCMD uint32 = 6 // 使用者下線請求 和 通知 UserOfflineRequestCMD uint32 = 7 UserOfflineNoticeCMD uint32 = 8 // 使用者改變狀態請求 和 通知 ChangeStatusRequestCMD uint32 = 9 ChangeStatusNoticeCMD uint32 = 10 // 修改使用者資料請求 和 響應 UpdateUserInfoRequestCMD uint32 = 11 UpdateUserInfoResponseCMD uint32 = 12 // 好友聊天請求 和 通知 FriendChatRequestCMD uint32 = 13 FriendChatNoticeCMD uint32 = 14 // 獲取使用者列表請求 和 響應 GetUserListRequestCMD uint32 = 15 GetUserListResponseCMD uint32 = 16 // 增加好友請求 和 響應 AddFriendsRequestCMD uint32 = 17 AddFriendsResponseCMD uint32 = 18 // 心跳請求 和 響應 HeartbeatRequestCMD uint32 = 19 HeartbeatResponseCMD uint32 = 20 // 上傳檔案請求 和 響應 UploadFileRequestCMD uint32 = 21 UploadFileResponseCMD uint32 = 22 // 獲取檔案列表請求 和 響應 GetFileListRequestCMD uint32 = 23 GetFileListResponseCMD uint32 = 24 ``` **二、客戶端** ``` 客戶端是使用c# + protobuf開發,只是簡單的實現了一個TCPClient類,其它的大多是介面上的操作了: ``` TCPClien: ```c# /// /// 傳送protobuf物件 /// /// 命令號 /// protobuf物件 /// public Int32 SendProtoMessage(Int32 cmd, IMessage message) { } 組裝資料包,傳送 /// /// 接收訊息執行緒 /// /// private void ReceiveThread(Object state) { } 啟動一個執行緒接收資料,把接收到的資料扔到佇列裡,再由DealQueueThread執行緒處理 在客戶端其實有一些場景並不合適使用非同步模式,比如 登入命令,註冊命令,使用同步模式處理會更方便 /// /// 處理訊息執行緒 /// /// private void DealQueueThread(Object state) { } 訊息佇列處理執行緒,把接收到的訊息用 ProtocolDecoder.Singleton.Decode 解包回撥 ``` ProtocolDecoder: ```c# 協議解析類,通過命令號把byte[]轉成相應的protobuf物件,並根據命令號回撥Action,最終回撥給介面 拿LoginRequest來舉例: 首先增加一個Login.proto檔案,裡面有兩個協議結構,LoginRequest用於請求,LoginResponse用於響應, 用protoc --csharp_out=. Login.proto編譯成c#類檔案,build.bat有編譯的命令 message LoginRequest { string UserID = 1; // 登陸的帳號 string Password = 2; // 密碼 int32 Status = 3; // 狀態 } message LoginResponse { Result Result = 1; // 返回值 UserInfo User = 2; // 使用者資訊 } 在ProtocolDecoder類裡增加一個回撥事件:publi