歡迎光臨
每天分享高質量文章

遊戲開發 —— 協議設計

點選上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 

摘要: 原創出處 https://my.oschina.net/u/1859679/blog/842513 「wier」歡迎轉載,保留摘要,謝謝!


協議就是通訊雙方能夠理解的一種資料格式。維基百科這麼定義網路協議:

網路協議為計算機網路中進行資料交換而建立的規則、標準或約定的集合。

協議設計包含三要素:

語法:語法是使用者資料與控制資訊的結構與格式,以及資料出現的順序。

語意:解釋控制資訊每個部分的意義。它規定了需要發出何種控制資訊,以及完成的動作與做出什麼樣的響應。

時序:時序是對事件發生順序的詳細說明

也就是說,語意表示要做什麼,語法表示要怎麼做,時序表示做的順序。我們要基於此來設計我的協議。

通常遊戲有一些特殊性,比如流量要儘量的少,安全性要求更高,以及對平臺支援足夠多等等。這一切的需求就要求遊戲協議設計,儘量簡單、通用,以及程式碼層上易擴充套件、解析效率足夠高等特點。

基於此,我需要從以下幾個層次來考慮遊戲協議的設計方案。

1
知識圖譜


因為知識點比較多,建議先讀知識圖譜,對整體結構有一個清晰的綜括。

2
協議三個層次

1

應用層
應用層主要是常用是解析方式定義和解析,主要的選型,主要是看你基於什麼需求了,適用於實際需求就好。

我們常用的協議型別,主要有這兩種:文字協議、二進位制協議。

文字協議

文字協議設計的目的就是方便人們理解,讀懂。如常見的http協議,一般的常見http協議如下:

這種格式非常貼近我們的文字描述,方便閱讀,而且目前HTTP也是客戶端瀏覽器或其他程式與Web伺服器之間的應用層通訊協議,適用非常廣泛。

但你也看到,有時候基於一個很簡單應答,就要帶上很多其他的頭資訊,這對於對流量有要求的遊戲應用來說,還是很浪費的。

優點

1、通用,適用廣泛

2、方便理解,可讀性好

缺點:

1、基於行讀,解析效率一般

2、攜帶附帶資訊過多,傳輸的效率低下

3、無狀態,伺服器不知道客戶端的狀態,必須基於客戶端的請求來回應,實時性低

4、很難嵌入其他資料,對二進位制支援差

如果你的遊戲對實時性要求不高,而且對流量要求不也是太高,文字協議也是個不錯的方式。一般短連線遊戲多適用這個。

二進位制協議


二進位制協議就是一串位元組流,是一個典型的Ip協議,一般通常包括訊息頭(essay-header)和變長的訊息體(body),訊息頭的長度固定,訊息體長度不固定,包含主要的內容主體

一般訊息頭會包含訊息體的長度,這樣就能基於頭資訊從資料流中解析出一個完整的二機制訊息了。

一般的格式如下:

我們看到head部分定義包含:

cmd:命令字

sign:驗證串

content-leg:訊息體長度

HeaderCRC:頭驗證(不是必須)

其中命令字是雙方協議檔案中規定好的,比如0x01表示登陸,0x02表示註冊等等,這些就是一個命令號。

sign是一個驗證字串,對訊息體資料進行一定加密驗證,保證資料安全。

content-leg是本次訊息體的長度。

body部分,比如我們如下定義:

message:login{

string username;

int64 passwoard;

}

我們看到,因為欄位的資料型別有定義,順序也有定義(第一個是string,第二個是int64),整個二進位制流讀取的的時候,基於順序讀取就可以很快的取出了。

優點

1、沒有冗餘欄位,傳輸高效,耗費流量小

2、解析速度快,基於基礎資料型別操作

缺點:

1、可讀性差,不利於除錯

2、擴充套件性差,對複雜資料結構支援不夠

如果你的遊戲,對實時性要求比較高,流量有要求,用二進位制比較好,一般大型多人網遊,使用二進位制協議來設計。

資料格式

以上我們看到了兩種協議型別,但對於訊息體的解析介紹很少,訊息體的格式決定了的他的語意和時序,格式不同資料的序列化和反序列化也是不同。比如message:login,你可以基於json來定義,也可以基於xml來定義,定義不同解析方式也各不相同。

一般的訊息體資料格式主要有以下幾種:json、protocolBuff、xml、自定義。

json

json是一種輕量級的資料交換格式,網際網路應用的很廣泛了。常用的框架也很多,推薦fastJson,解析速度還是不錯的。json的好處是,開源,格式統一,解析速度也還可以。缺點就是會有一些冗餘字元,不夠簡潔。

protocolBuff

protocolBuff是是google提供的一個開源序列化框架,類似於XML,JSON這樣的資料表示語言。但是比這些佔用空間都小,沒有冗餘欄位。而且好處是靈活,解析速度快,易於開發(基於配置自動生成程式碼),可支援語言也比較多。一條訊息資料,用protobuf序列化後的大小是json的10分之一,xml格式的20分之一,是二進位制序列化的10分之一

xml

不多解釋了,大家都用有過,強烈不建議使用這種,除了無效字元過多(標簽),而且解析效率比上面兩種都是很低的。

自定義

自己定義就是自己定義解析方式,比如透過檔案定義好一個訊息的結構,第一個欄位是什麼型別,第二個欄位什麼型別…等等,基於此自己寫工具解析。好處是對外協議不透明,解析效率和傳送效率都還不錯,缺點就是開發難度高,不容易維護。

各種格式優缺點如下:

2

安全層

遊戲通訊,安全也很重要,不然協議被破解,使用者刷資源,整個遊戲的平衡性就被破壞了,輕者影響其他玩家體驗,重則遊戲直接被廢。

一般的安全處理就是對協議進行加密。

一般有以下幾種:


常規加密

採用對稱加密或者hash加密來對訊息內容進行加密,兩端採用同一種加密演演算法,基於同一個金鑰對訊息體進行加密換算,以此來檢視資料是否一致。

金鑰可以使用者登陸的時候獲取一次。還有一種是基於每個使用者金鑰不同,以此防止金鑰洩露大範圍影響全服玩家。

動態加密

動態加密,可以提前設定一個私有金鑰庫,裡麵包含一定數量的金鑰,每次客戶端請求的時候,基於協議號來設計一個演演算法獲取其中一個金鑰。每個協議的金鑰都是在協議到達的時候時時獲取的,這樣即便某一個協議的金鑰被破解,對其他協議依然無效。

其他

採用非對稱加密,或者加鹽處理。這個不詳講了,非對稱加密速度太慢了,不建議。

3

傳送層

考慮服務端的承載成本,以及手機上游戲網路環境差,原則上UDP是比TCP更適合的方式。但是由於遊戲對於資料完整性、安全性要求比較高,採用TCP的又可靠與安全。

目前採用netty作為推送伺服器的也有支援上百萬連線的應用了,tcp這塊效能對於一般遊戲支援足夠了。長連結遊戲多採用分割槽分服來應對高併發壓力,短連結多採用分散式來應對。

3
一些問題

位元組序


二進位制協議中,位元組序需要註意,跨語言、平臺通訊的時候會出現亂碼問題。目前的位元組序主要有,Little endian和Big endian之分,也就是常說的大頭和小頭之分。

具體是大頭在前還是小頭在前,這個和主機的cpu有關係PowerPC系列採用big endian方式儲存資料,而x86系列則採用little endian方式儲存資料。這個在手機主機上也會出現。

應對方案是:

客戶端和服務端強制採用一種位元組序,一般採用網路位元組序(big endian)

浮點數

協議中出現浮點型別要特別註意,浮點型別的傳送上面位元組序處理OK了,還得註意浮點數的多平臺運算不一致問題。

比如遊戲中要對尋路、戰鬥等公式計算,牽扯到浮點數了,有可能前後端算出的不一致,以Arm為例,Arm的浮點數就有軟模擬、硬體IEEE-754相容、SIMD下IEEE-754不相容三種情況。

應對方案是:

1、統一一種格式,比如前後端都採用軟模擬,或者強制採用硬體IEEE-754(軟模擬速度慢)

2、轉換為定點數,也就是浮點轉換為整數(速度快)

end




如果你對 Dubbo 感興趣,歡迎加入我的知識星球一起交流。

知識星球

目前在知識星球(https://t.zsxq.com/2VbiaEu)更新瞭如下 Dubbo 原始碼解析如下:

01. 除錯環境搭建
02. 專案結構一覽
03. 配置 Configuration
04. 核心流程一覽

05. 拓展機制 SPI

06. 執行緒池

07. 服務暴露 Export

08. 服務取用 Refer

09. 註冊中心 Registry

10. 動態編譯 Compile

11. 動態代理 Proxy

12. 服務呼叫 Invoke

13. 呼叫特性 

14. 過濾器 Filter

15. NIO 伺服器

16. P2P 伺服器

17. HTTP 伺服器

18. 序列化 Serialization

19. 叢集容錯 Cluster

20. 優雅停機

21. 日誌適配

22. 狀態檢查

23. 監控中心 Monitor

24. 管理中心 Admin

25. 運維命令 QOS

26. 鏈路追蹤 Tracing


一共 60 篇++

贊(0)

分享創造快樂