前段時間看到一篇博文《可在廣域網部署運行的即時通訊系統 -- GGTalk總覽(附原始碼下載)》,他是用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:
/// <summary>
/// 發送protobuf物件
/// </summary>
/// <param name="cmd">命令號</param>
/// <param name="sendMessage">protobuf物件</param>
/// <returns>已發送長度</returns>
public Int32 SendProtoMessage(Int32 cmd, IMessage message)
{
}
組裝資料包,發送
/// <summary>
/// 接收訊息執行緒
/// </summary>
/// <param name="state"></param>
private void ReceiveThread(Object state)
{
}
啟動一個執行緒接收資料,把接收到的資料扔到佇列里,再由DealQueueThread執行緒處理
在客戶端其實有一些場景并不合適使用異步模式,比如 登錄命令,注冊命令,使用同步模式處理會更方便
/// <summary>
/// 處理訊息執行緒
/// </summary>
/// <param name="state"></param>
private void DealQueueThread(Object state)
{
}
訊息佇列處理執行緒,把接收到的訊息用 ProtocolDecoder.Singleton.Decode 解包回呼
ProtocolDecoder:
協議決議類,通過命令號把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類里增加一個回呼事件:public Action<LoginResponse> OnLoginResponse;
在GetMessage 和 OnEvent方法里增加相關的代碼
在LoginForm_Load里注冊事件回呼方法ProtocolDecoder.Singleton.OnLoginResponse += OnLoginResponse;
最后,使用TCPClient.Singleton.SendProtoMessage(CMD.LoginRequestCMD, request);發送登錄命令后,會回呼到OnLoginResponse方法,
注意一點哈:登錄方法其實使用同步模式更加方便合理,我這里是使用異步,所以要增加一個BaseTask類用于修改按鈕的狀態
三、服務端
服務端使用golang + protobuf開發,通訊組件使用 [zinx](http://github.com/aceld/zinx), zinx內部已經實作了
4個位元組的長度 + 4個位元組的包長 + 資料包 的協議
只要把命令號和處理物件系結,并實作Handld方法就成了,其他的就是業務代碼了
在服務端里,使用gin實作了一個簡陋的web服務,用于下載頭像,檔案等資源
使用TCP協議上傳檔案后,同步到其他web或者CDN服務,再把URL回傳給客戶端
這種架構對客戶端和服務端都是很好的,實作簡單,并且能大大減少服務端壓力,
原始碼:https://github.com/bccber/gogotalk
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/170388.html
標籤:其他
上一篇:python基本輸入與輸出
