客戶端同步 方式是,客戶端之間發送數據,獲得數據后,合並到最近的一幀 來處理。服務器心跳繼續保持
比如 ab之間 同步,服務器心跳 0.5秒一次,那么 一次比作 一幀。 a發b的時候,正好是 30幀時候,那么a以31幀的數據方式 給a b同時 接收。返回后 等待 心跳是 31的時候,再處理 之前 收的數據。
這樣的好處就是,服務器壓力小,服務器只要 負責心跳 以及 客戶端 相互發送就可,不需要 任何記錄操作。
但缺點很明顯,發送量太大,ab之間發送,就是2次 給 客戶端發,如果是 群體幾十號玩家相互發,那一個玩家發一條 ,服務器就要發好幾十條,最后變成n*n
所以,我改進了方法,采取 服務器同步法,同樣 服務器心跳不變,時時刻刻告訴客戶端 目前 是 第幾幀。
客戶端之間 相互發送,服務器 記錄 ,在心跳當中 發射。
比如 ab 之間 互發消息。服務器記錄的是 a 發的消息 和 在第幾幀發的,當然因為延遲,我們肯定是 要再多加1幀,告知 是下一幀 轉發客戶端。那么心跳在 下一幀的時候,就發現有 一條記錄,要求 ab都要收到 一條記錄,然后 心跳就 不僅僅是發幀,還包含了 相關數據。
這樣的好處就是,服務器 發送量 不會因為 並發大而 增加,發送量是 固定的。
壞處也有,就是 心跳每次都會檢索一次每個 客戶端 當前幀有沒有數據要 發送。
相互發送服務器 片段代碼,這里只負責存數據,不用來發送
//同時通知雙方 static void OnSendDouble(string Type, string Playid, string Otherid, NetIncomingMessage msg) { //這個區塊有存在 JsonDatas message = new JsonDatas(); message.jsons["type"] = Type; message.jsons["Frame"] = Frame + 1; message.jsons["playid"] = Playid; string json = JsonConvert.SerializeObject(message); //如果 這個幀 已經發射一次以上了 if (ServerModel.getInstance().OnSendeMessageDictionary.ContainsKey(Playid + "," + (Frame + 1))) { //Console.WriteLine(" 已經多次 " + Playid + "," + (Frame + 1)); ServerModel.getInstance().OnSendeMessageDictionary[Playid + "," + (Frame + 1)].Add(json); } else { // Console.WriteLine("第一次 " + Playid + "," + (Frame + 1)); List<string> jsonlist = new List<string>(); jsonlist.Add(json); ServerModel.getInstance().OnSendeMessageDictionary.Add(Playid + "," + (Frame + 1), jsonlist); } //如果 這個幀 已經發射一次以上了 if (ServerModel.getInstance().OnSendeMessageDictionary.ContainsKey(Otherid + "," + (Frame + 1))) { // Console.WriteLine(" 已經多次 " + Otherid + "," + (Frame + 1)); ServerModel.getInstance().OnSendeMessageDictionary[Otherid + "," + (Frame + 1)].Add(json); } else { // Console.WriteLine("第一次 " + Otherid + "," + (Frame + 1)); List<string> jsonlist = new List<string>(); jsonlist.Add(json); ServerModel.getInstance().OnSendeMessageDictionary.Add(Otherid + "," + (Frame + 1), jsonlist); } }
public static void Confrontation() { while (true) { Thread.Sleep(500); // Output("目前" + Frame); List<NetConnection> all = s_server.Connections; // get copy // all.Remove(msg.SenderConnection); if (all.Count > 0) { foreach (NetConnection NT in all) { NetOutgoingMessage om = s_server.CreateMessage(); JsonDatas message = new JsonDatas(); message.jsons["type"] = "7"; message.jsons["Frame"] = Frame; message.jsons["TF"] = 0; string id = ServerModel.getInstance().TSenderConnectionlDictionary[NT]; //如果 這個幀 有過發射 if (ServerModel.getInstance().OnSendeMessageDictionary.ContainsKey(id + "," + Frame)) { message.jsons["TF"] = 1; message.jsons["msg"] = JsonConvert.SerializeObject(ServerModel.getInstance().OnSendeMessageDictionary[id + "," + Frame]); string json = JsonConvert.SerializeObject(message); om.Write(json); s_server.SendMessage(om, NT, NetDeliveryMethod.ReliableOrdered, 0); ServerModel.getInstance().OnSendeMessageDictionary.Remove(id + "," + Frame); } else { string json = JsonConvert.SerializeObject(message); om.Write(json); s_server.SendMessage(om, NT, NetDeliveryMethod.ReliableOrdered, 0); } } } Frame++; } }
上面這個是心跳的片段代碼
數據是 list方式,因為 可能一幀 會多次操作。key 是 id+幀 用完刪