NetWay
項目主頁:http://code.google.com/p/netway
使用效果:http://blog.csdn.net/shallwake/archive/2009/12/04/4942099.aspx
一,結構概覽:
首先看一下主要功能模塊之間的關係,方框表示主要的類,橢圓表示該類完成的功能。
服務端
客戶端
可以看出,服務端的邏輯模塊爲Controller。客戶端的邏輯模塊爲Client。我們所需要做的就是繼承這兩個類,實現接口供引擎調用,然後擴展自己的邏輯功能。
二,通信協議
當然,還有一個接口必須擴展,那就是客戶端與服務端的通信協議,NetWay系統自帶了EventDefault類默認實現該接口,而且滿足大多數需求。
我們看看通信協議的實現:
Message Header長度是固定的,PayLoad可根據需要進行擴展。下面一一講解各消息字段的含義。
- ClientID:保留位,默認爲0,可根據需求擴展,如放入軟件版本號。
- AppNameHash:程序名的HASH值,供服務端讀取後調用對應邏輯模塊。
- payLoadSize:數據包體長度。
我們不需要關心複雜的消息處理機制,引擎已經幫我們做好了,所以只需創建消息,設定相關字段,傳遞給引擎即可。讀取消息類似。
再看看引擎的默認消息實現類,EventDefault。它實現了Event接口以便引擎調用,並且定義了常規的通信協議,用戶可根據需要改造他。其中最主要的有3個,
eventType,playerId還有Message
。對於一般情況,我們只需 new EventDefault()並設置好這3個字段,然後交給引擎即可。eventType表示該數據包的類型,playerId表示發送者 ID,Message表示該數據包的消息。下面是eventType的實現:
- public static final int C_LOGIN = 1001;
- public static final int S_LOGIN_ACK_OK = 1002;
- public static final int S_LOGIN_ACK_FAIL = 1003;
- public static final int SB_LOGIN = 1004;
- public static final int C_LOGOUT = 1005;
- public static final int SB_LOGOUT = 1006;
- public static final int S_DISCONNECT = 1007;
- public static final int C_GET_PLAYERS = 1107;
- public static final int S_GET_PLAYERS = 1108;
- public static final int C_CHAT_MSG = 1201;
- public static final int SB_CHAT_MSG = 1202;
C_*表示由客戶端發送,S_*表示由服務器發送,SB_*表示服務器廣播。關於消息填充與讀取的實現,可參考源碼。
有了消息的實現後,客戶端與服務器就可以通信了,其中涉及一些java與C++的差異性,感興趣的還是參考源碼吧。。
三,定製服務端邏輯
下面講解下如何用NetWay定製自己的系統。以服務端爲例:
首先,創建ChatRoom類並繼承NetWay.jar裏的Controller類,然後,我們需要實現以下5個純虛函數:
- initController();
- String getAppName();
- Player createPlayer() ;
- Event createEvent() ;
- processEvent(Event e);
initController 主要用於一些額外的初始化;getAppName指示此模塊的名稱,方便引擎調用;createPlayer創建player數據,暫時返回 playerDefault,用戶可擴展他;createEvent也暫時返回eventDefault,用戶可擴展。processEvent爲核心邏輯,自動獲取消息。其中最主要的只有用紅色標記的那2個,其餘3個都是默認實現。
配合繼承而來的2個函數
sendEvent(Event e, Player p)
與
sendBroadcastEvent(Event e, Collection players)
就可實現各種邏輯了。其實,processEvent就是引擎傳遞消息進來的接口,而 sendEvent 與 sendBroadcastEvent 則是傳遞消息給引擎的接口。以下是該5個函數的實現:
- public String getAppName() {
- return "ChatRoom";
- }
- public void initController(Config gc) {
- players = new Hashtable();
- }
- public void processEvent(Event e) {
- switch (e.getType()) {
- case EventDefault.C_LOGIN:
- login(e);
- break;
- case EventDefault.C_LOGOUT:
- logout(e);
- break;
- case EventDefault.C_CHAT_MSG:
- chat(e);
- break;
- case EventDefault.C_GET_PLAYERS:
- getPlayers(e);
- break;
- }
- }
- public Player createPlayer() {
- return new PlayerDefault();
- }
- public Event createEvent() {
- return new EventDefault();
- }
關於ProcessEvent接受消息後,如何處理它的函數就不列出來了,無非就是createEvent()後再 setEventType()+setMessage()。然後用繼承而來的sendEvent或者sendBroadcastEvent交給引擎發送。
另外還需注意的是,ChatRoom類必須在頂部指定包名:package netway.controller; 並且需要導入NetWay.jar庫與log4j庫。
然後打包成ChatRoom.jar,放入Plugins目錄即可投入使用。
四,定製客戶端邏輯
客戶端的定製比較簡單,與服務端類似,繼承Client類並擴展即可。
五,其他問題
由於我第一次接觸靜態庫的編寫,貌似Debug版與Release版不同,使用庫的話必須使用對應版本,所以兩種版本我都提供了。還有用MFC使用庫的話,必須是選擇“在共享Dll中使用MFCl",否則連接錯誤。。目前原因不明,猜測是靜態庫沒使用包名,導致符號錯誤,下來我會改進。。另外,關於靜態庫的 使用方法可百度解決。
還有測試版代碼可能有誤,還在不斷改進。以後會繼續更新
最後還是建議看下服務端Controller類與客戶端Client類源碼,然後再看看ChatRoom例子。該系統本來就實現的很簡單,最好把整個源碼都看一遍。。雖然註釋不夠,有一點也是中英文混雜。。。但是代碼還算規範。。封裝也很淺,所以還是有學習價值。