單一世界 2 報文介面

2021-05-22 03:23:03 字數 1209 閱讀 7262

報文在所有的cs架構中,是很重要的基礎。因此,在所有工作開展之前,有必要先對報文進行分析。作為乙個通用的伺服器,那麼他的報文格式必須受標準 約束,在靈活性跟可擴充套件性方便是很重要的考慮因素,而對具體的業務規則反而不能深入的介入。魔獸世界的報文具有他本身私有的業務規則,單一世界是為網遊戲 設計的,所以不可避免得要加入業務規則。乙個折衷的方案是,伺服器內部具有通用的標準規則,而通過轉換器將魔獸世界的規則轉換為單一世界的通用規則。

從 worldsock.cpp開始看魔獸世界的報文結構,在int worldsocket::handle_input_missing_data (void)函式,接收客戶端發來的報文。

首先,解開報文頭:struct clientpktheader ,用的sarc4解碼。關於加密解密在後續中繼續討論。在網路傳輸中,size跟cmd按照網路慣例是以大端方式儲存,因此還需要進行位元組序轉換。

其 次,是報文體。讓我十分差異的是,報文體本身沒有經過任何處理,顯然只是個緩衝區。而報文體結構是根據命令,在具體的業務中進行處理。報文體主要容納數值跟字串,數值是按大端格式儲存的,而字串是以0結尾儲存的。

還有 乙個很奇怪的是,在流方式的cs中,報文頭的邊界是很重要的,通常我用0x5555來作為報文邊界。這種能避免每個命令之間由於網路傳輸中無意中新增入無 用的位元組引起的問題。因為沒有報文邊界的話,將導致後續所有的報文無法解碼,且無法恢復,而 報文邊界的存在,將很快的從下乙個正確報文開始重新解碼。

在方法bool readpackguid(uint64& guid),也是蠻好玩的,他加了乙個位元組,作為位圖。後續的連續8個位元組中,只有在第乙個位元組中的位元位是1才是有效的,如果該位元組為0,那麼該位元組就被拋棄了。這個方法很有趣,一般的guid中,為0的位元組還是比較多的,因此壓縮空間還比較大。還有一種也可以借鑑,類似於utf8的編碼,只使用乙個位元組中的7位,當乙個位元組的最高位是1的話,那麼就結束了,這種方法最差情況跟readpackguid是一樣的,多了乙個位元組。而最好的情況不需要額外的位元組。不過從壓縮角度來看,readpackguid應該更有效。

從opcodes.h中,可以看到有num_msg_types=0x507=1287個操作碼,包括服務端跟客戶端,但真正用到的沒有這麼多。我會先完成乙個前置機,負責接收所有的報文,然後**給伺服器,以及接收伺服器的報文**給客戶端。在未來的設計中,我會利用這個前置機,將一部分工作交給其他服務程序,同時又不影響現在的服務架構。當然,前置機的另外乙個工作還包括解析報文,以便重演所有的過程,這個是個很有挑戰性的任務,需要多方面配合,暫時先放著。

單一世界 3 簡單報文

我們知道,報文在網路上的流轉主要是以二進位制方式傳輸,而報文具體的含義依賴於收發雙方的私有約定。而xml設計於一種通用標準,在業務上具有更廣泛的適用性,但其解析上有較高的複雜度,帶來效能損失。我們需要設計一種高效 簡單 更強業務描述能力的報文協議,顯然,在報文定義具體業務含義的內容是不可行的。我將這...

單一世界架構初探之登入管理

現在我們進入實質性的 階段,首先是登入管理。單點登入,意味著,所有的請求都將被乙個ip處理。而海量請求,意味著所有的登入管理都會在乙個ip的完成,天啦,如果到了10m那是什麼概念。即 使1m s的處理速度,也要10s才能完成乙個登入管理,那我估計,這個應用早被人罵了體無完膚,當然,魔獸世界可能例外,...

單一世界架構初探之動態分割槽

靜態分割槽,讓每個伺服器負責特定區域,技術上相對簡單 而動態分割槽實際上更接近於集群技術,按照負載自動調整區域,但技術更加複雜。上面所論述的計算遷移就是為了討論動態分割槽做的準備。在 魔獸世界中,暴風城和閃金鎮是2個典型,暴風城是個主城,人多 地形複雜,而閃金鎮周圍都是森林,人也多是匆匆過客,除了少...