前面幾篇文章用akka寫了helloworld和echoserver,為了更進一步學習akka,本文將會實現乙個非常小的rpg遊戲server:minirpg。
由於是迷你rpg,所以邏輯非常easy。server能夠處理四種操作:建立玩家、給玩家加經驗、公升級、查詢玩家資訊。以下是player類的**(getters和setters省略):
public class player
public void levelup() }}
minirpg底層使用tcp協議,訊息使用json格式。完整的訊息格式例如以下圖所看到的:
前八個位元組能夠覺得是訊息頭。當中前四個位元組是訊息id。後四個位元組是json字串長度。其餘位元組是訊息體,也就是utf8格式編碼的json字串。
minirpg設計了三個介面來表示遊戲訊息,這三個介面都是marker介面。裡面未定義不論什麼方法。例如以下圖所看到的:
minirpg使用gson來編碼和解碼json字串,為了把json解析為對應的訊息物件。須要乙個訊息id和class之間的對映關係。msgregistry類便是要建立起這樣乙個對映關係,以下是它的完整**:
public class msgregistry private static void register(int msgid, class> msgclass) public static class> getmsgclass(int msgid) public static int getmsgid(class> msgclass) public static int getmsgid(object msg) }
minirpgserver的actor系統例如以下圖所看到的:
tcpserver負責監聽tcp連線。連線建立之後。交給codec處理。codec將收到的位元組編碼成訊息物件。然後交給msghandler處理。對於每條請求訊息。msghandler都會產生一條響應訊息。響應訊息被codec編碼之後傳送到client。
以下具體介紹整個actor系統是怎樣實現的。
tcpserver是乙個untypedactor,例項化tcpserver時,我們把msghandler引用傳給它:
public class tcpserver extends untypedactor
}
tcpserver僅僅關心四種訊息。以下是onreceive()方法實現:
@override
public void onreceive(object msg) throws exception else if (msg instanceof bound) else if (msg instanceof commandfailed) else if (msg instanceof connected)
}
integer訊息通知tcpserver繫結到某個port,準備接收client連線。假設收到bound訊息,則port繫結成功。server正常啟動。假設是commandfailed訊息。則server啟動失敗:
private void startserver(int port)
假設是connected訊息。說明有client連線已經建立,tcpserver建立乙個子actor(也就是codec)來處理client連線:
private void registercodec(actorref connection)
msgcodec主要負責訊息的編碼和解碼。為此,msgcodec內部使用了乙個bytestring來快取接收到的位元組:
public class msgcodec extends untypedactor
}
假設msgcodec收到的是received訊息,說明有資料到達。msgcodec嘗試解碼出乙個訊息物件。假設收到的是gamemessage訊息。msgcodec將其編碼為byte然後傳送給client。
假設收到的是connectionclosed,說明連線已經斷開了:
@override
public void onreceive(object msg) throws exception else if (msg instanceof connectionclosed) else if (msg instanceof gamemessage)
}
每當有資料到達時。decodemsg()方法都會被呼叫。decodemsg()先確定能否夠把訊息頭解碼出來,假設不能,就繼續等待很多其它的位元組到達。
假設訊息頭完整到達,decodemsg()就能夠知道訊息體的長度,然後等到訊息體完整到達。之後依據訊息id和json字串解碼訊息物件。然後通知msghandler:
private void decodemsg() }}
private object decodemsg(int msgid, bytestring jsondata)
訊息的編碼就簡單多了,**例如以下所看到的:
private bytestring encodemsg(object msg)
遊戲邏輯由msghandler來處理。
由於僅僅是個demo,所以msghandler內部使用hashmap來模擬資料庫。以下是msghandler的完整**:
public class msghandler extends untypedactor else if (msg instanceof addexprequest) else if (msg instanceof leveluprequest) else if (msg instanceof getplayerinforequest)
}private int createplayer(createplayerrequest req)
private int addexptoplayer(addexprequest req)
private int levelupplayer(leveluprequest req)
private playerinfo getplayerinfo(getplayerinforequest req)
}
public static void main(string args)
} 為了測試miniserver。我寫了個簡單的客戶端程式。詳細實現就不在這裡介紹了。
POSA邊讀邊寫 1
拿到這本書,就感覺posa是繼gof之後的又一經典之作。序中介紹,posa拓展了模式的範圍,從原來的設計模式,拓展了新的高層次的體系機構模式,和底層的和程式語言相關的慣用法模式。提出了新的模式分類方法 根據規模 抽象層次 提出了模式系統,來幫助我們利用模式來設計 什麼是模式 模式是乙個描述,它描述了...
邊學邊寫資料結構之線性表
學習的時候能將自己學到的東西寫出來也是一種很好的學習方法,它既能加深學習的效果,又能知道自己對學習內容的了解情況。如果你寫不出來也就說明你對所學的內容並不是完全了解,還有值得重新學習的地方。本人大學只學習過乙個學期的c 語言,其他諸如資料結構與演算法壓根就沒有學過,奈何畢業後從事的是與軟體開發有關的...
Python學習筆記 邊學邊寫第乙個爬蟲
python學習筆記 邊學邊寫第乙個爬蟲 請求網頁 import requests response requests.get print response.text 通過chrome開發者工具找到乙個headers 請求網頁 import requests headers response req...