--[[ KCP 断开 ,TCP没有断开的重连 --]] local KcpReconnectManager = {} local private = { cacheBattleFrames = {}, -- 缓存的大补帧数据 lastReconnectEndFrameLen = nil, -- 上次kcp重连的帧长度 lastReconnectBattleID = nil, -- 上次kcp重连的战斗id } local EventSystem = require('Event/EventSystem') local reconnect_pb = require "Proto/battle_reconnect_pb" function KcpReconnectManager.Init() NetManager.RegisterMsgCB(MessageEnums.MessageG2CNeedReconnect, private.OnG2CNeedReconnect ) end --接收到服务器通知需要kcp重连下 ---这个协议有个问题要修复 :服务器收到KCP的ping就会发一次这个协议,ping一秒一个,此时TCP堵塞,那么再2秒时一下收到2个这协议。 --- 导致后续收到重复的补帧数据,帧数量超过服务器帧量,进而二次补帧出现越界,二次补帧中不带数据。表现为丢失帧数据了 --- 修改方案:如果在同一个战斗中kcp补帧发送的EndFrameLen相同,则不再发送 function private.OnG2CNeedReconnect() EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.SyncBattle,"[sync]G2CNeedReconnect") if MultiplayManager.CurConnectType == LuaConst.SyncConnectType.TCPReconnectInBattle then EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.SyncBattle,"[sync]G2CNeedReconnect_DropByTCP") logging.warn(LTAG.WARN,"【gws】 KCP重连发现当前正处于 TCP 战斗内重连中,为防止帧重复,需要阻断kcp重连 ") return end MultiplayManager.CurConnectType = LuaConst.SyncConnectType.KCPReconnect local beforeEndFrameLen = BattleExt.GetServerMsgCount() if private.lastReconnectBattleID == BIManager.GetSyncBattleGRoomID() and private.lastReconnectEndFrameLen == beforeEndFrameLen then EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.SyncBattle,"[sync]G2CNeedReconnect_Drop") logging.warn(LTAG.WARN,"【gws】 KCP重连发现G2CNeedReconnect和上次重连一样的协议,不做任何操作!battleID: ",private.lastReconnectBattleID, ",endLength=",private.lastReconnectEndFrameLen) return end --关闭KCP连接 KCPTransport.Close() --保存还没有处理的帧数据,放入到main的处理队列中 ;注意:队列千万别被清理掉 LogicUpdateManager.GetFrameDataFromKCPCache(true) local endFrameLen = BattleExt.GetServerMsgCount() private.lastReconnectEndFrameLen = endFrameLen private.lastReconnectBattleID = BIManager.GetSyncBattleGRoomID() --清理kcp的缓存数据 KCPTransport.ClearKCPData() BattleExt.SetServerMsgCount(endFrameLen) --关闭主循环 LogicUpdateManager.StopFightUpdate() MultiReconnectManager.HasKCPNeedReconnect = true --发送协议告诉服务器我拿到多少帧的数据了,服务器以这个数给我大补帧 local connectInfo = MultiplayManager.GetKCPConnectInfo() local msg = reconnect_pb.C2GInBattleReconnect() msg.BRoomID = connectInfo.roomId msg.Player = LevelPlayerManager.MyPlayerIDInRoom msg.EndFrameLen = BattleExt.GetServerMsgCount() NetManager.SendMessage(MessageEnums.MessageC2GInBattleReconnect,msg) logging.crit(LTAG.CRIT,"KCP 1/4 :服务器让客户端断开KCP,并尝试请求重连信息 FrameCount =" , msg.EndFrameLen, " curServerFrame = ", LogicUpdateManager.GetServerFrame(), ",beforeEndFrameLen=", beforeEndFrameLen) table.clear(private.cacheBattleFrames) EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.SyncBattle,"[sync]G2CNeedReconnect", msg.EndFrameLen, LogicUpdateManager.GetServerFrame(), beforeEndFrameLen) end -- 接收到服务器的大补帧(帧数据在C#中),连接IP function KcpReconnectManager.OnBattleFrameDatas(msg) table.insert(private.cacheBattleFrames, msg.BattleData) if not msg.IsEnd then return end local count = #private.cacheBattleFrames local battleFrameBytes = table.concat(private.cacheBattleFrames) BattleExt.ParseBattleData(battleFrameBytes) table.clear(private.cacheBattleFrames) MultiReconnectManager.HasKCPNeedReconnect = false local connectInfo = MultiplayManager.GetKCPConnectInfo() KCPTransport.Connect(connectInfo.ip ,connectInfo.port ,connectInfo.roomId ,connectInfo.playerId ) -- 不连接暂时没办法让Lua获取到大补帧数据 MultiplayManager.IsFromStartEnter = false MultiReconnectManager.SetNeedWaitReconnectDone(true) --获取大补帧数据,并开始处理 LogicUpdateManager.GetFrameDataFromKCPCache() LogicUpdateManager.SetServerReplenishFrame(KCPTransport.GetCurserverFrame()) --设置快速补帧的值 ,快速补帧到大补帧的数字时,不做表现 logging.crit(LTAG.CRIT, "KCP 2/4 :服务器返回重连大补帧信息,客户端缓存大补帧 ;客户端重连IP; FrameCount =" , BattleExt.GetServerMsgCount()) EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.SyncBattle,"[sync]KCPReconnect" , BattleExt.GetServerMsgCount(), count) end return KcpReconnectManager