專案背景
多人線上棋牌遊戲,客戶端為手機(J2ME),透過行動網路與伺服器通訊。手機運算弱、流量貴,設計須充分考量。全程參與設計並完成 90% 核心代碼。
語言選擇:Java
- Linux 環境,排除 MS 技術;Mono 不成熟。
- C++ 雖快,但易陷入代碼惡夢;Java 網路能力強、開發週期短、框架豐富、寫出爛代碼也不容易。
一、網路通訊
HTTP vs Socket
- HTTP 相容性最好,但無狀態需輪詢,且 Header 開銷大(測試每秒輪詢一局牌耗 1 元以上 GPRS 費),不可接受。
- 選擇 Socket,自行實作執行緒管理、狀態監控、物件池、控制台等。
Java NIO 非同步 I/O
- 基於事件驅動,單執行緒處理大量連線,提升效能。
- 每客戶端一個
SocketChannel 存活整個生命週期。
- 偵測斷線:讀取回傳 -1 或拋出
Connection reset 例外,清理資源。
二、通訊協定:極致省流量
- 指令以位元組而非字串編碼,流量減半。
- 撲克牌編碼:1 位元組,高 4 位花色、低 4 位點數(黑桃 3 = 0x03)。
- 大整數(積分)用 4 位元組:
translateLong/translateByte 位移操作互轉。
三、資料庫連線池:Apache Commons DBCP
- 需三個 JAR:
commons-collections、commons-dbcp、commons-pool。
BasicDataSource 設定驅動、URL、帳密、初始連線數、最大閒置、超時回收。
- 取得連線:
fac.createConnection(),用畢 conn.close() 歸池。
四、撲克牌生成與洗牌
- 初始化 54 張牌至
HashMap,鍵為 0-53,值為位元組編碼。
- 大小王編碼 0x4D、0x4E。
- 隨機抽取:
Math.random() * 大素數 % 54,取得後從 Map 移除防重複。大素數可控制發牌分布。
五、執行緒管理:避免互相控制
Thread.destroy() 從未實作(拋 NoSuchMethodError),不可用來銷毀執行緒。
- 採用共享旗標/物件通訊:主執行緒啟動工作執行緒,工作執行緒自管生命週期,雙方透過共享方法溝通(Sun 推薦做法)。
六、非同步訊息:JMS Message Bean
- 記錄積分、日誌等耗時操作封裝為 Value Object 送入 JMS Queue,即時返回不阻塞遊戲主流程。
- JMS 特性:訊息必達且僅消費一次、支援持久化、Point-to-Point Queue 先進先出。
- JBoss 4.0 部署極簡單,
jboss.xml 宣告目的地不存在自動建立。
七、啟動與關閉:資源預載與 Shutdown Hook
- 啟動時初始化連線池、JMS 連線、靜態工具類,減少運行時建立開銷。
- 註冊
Runtime.getRuntime().addShutdownHook(new Hook()),Hook.run() 中釋放連線池、關閉 JMS,實現優雅關閉(類似 Ctrl+C)。
結語
手機遊戲伺服器端開發核心在於:選對技術棧、極致壓縮協定、善用非同步機制、優雅管理資源生命週期。Java+NIO+JMS 組合在本專案證明高效可靠。