採用經典 Server-Client 架構,Server 負責監聽連線、管理遊戲狀態、轉發訊息;Client 負責 UI 互動與 Server 通訊。兩個 Client 之間無直連,所有通訊經 Server 代理。
new Server() 綁定預設埠 1991,Listen()。while(true) 輪詢 AcceptTcpClient(),收集兩個 NetworkStream。AcceptClient1Data、AcceptClient2Data 執行緒持續讀取資料。SendDataForClient(msg, clientIndex) 向指定 Client 發送位元組陣列。new Client().Connect(serverIP, 1991)。AcceptServerData() 持續讀取 Server 推送訊息。SendDataForServer(msg) 向 Server 上報動作。byte[108],極度不靈活,易造成資料截斷或讀取殘留。"StartPokers" + 序列化牌組、"OK"、"AreYouLandLord" 等。PokerGroup 自行實作 byte[] 序列化/反序列化。

| 問題 | 影響 | 改進建議 |
|---|---|---|
| 固定 108 bytes 緩衝區 | 長訊息截斷、短訊息殘留干擾 | 採用 長度前綴 或 分隔符 協定,動態緩衝區 |
| 阻塞式 Read 無逾時 | 網路卡頓導致執行緒卡死 | 使用 NetworkStream.ReadAsync + CancellationToken |
| 無心跳/重連機制 | 斷線無法恢復 | 實作 Ping/Pong 心跳,Client 端自動重連邏輯 |
| 字串解析協定 | 效能低、易誤判、難擴充 | 改用 Protobuf / MessagePack / JSON 序列化 |
| Thread.Sleep 同步 | UI 凍結、延遲不可控 | 全面改為 async/await 非同步模式 |
public void AcceptClient1Data() {
var ns = _client1.GetStream();
while (true) {
byte[] buffer = new byte[108];
int read = ns.Read(buffer, 0, buffer.Length); // 阻塞讀取
string msg = Encoding.Default.GetString(buffer, 0, read);
ProcessMessage(msg, 1); // 解析並分派
}
}