require "Message/CommonProto_pb" require "Message/MessageTypeProto_pb" require "Base/Queue" Network = {} Network.__index = Network function Network.New(type, socket) local instance = { type = type, socket = socket } instance.isConnected = false instance.waitingTimes = 0 --空闲时间 instance.maxWaitingTimes = 20 -- 最大心跳等待时间(秒) instance.bIsStartListenHeartBeat = false instance.resendTimes = 0 --记录消息重发次数 instance.sendFlag = false --监听收到消息的标记,发送时标记为true,收到消息则标记为false instance.maxResendTimes = 3 --最大重发次数,超过该时间则取消发送 instance.sendWaitTime = 0 --记录消息等待时间(秒) instance.maxSendWaitTime = 5 --消息重发等待时间(秒),超过该时间会重发消息 instance.sendFunc = nil --请求缓存 instance.sendFuncQueue = Queue.New() --请求缓存列表,当一帧发送多个请求时,缓存等待上一个请求收到回调时,执行下一个请求 instance.re_resendTimes = 0 --记录断线重发次数 instance.reconnectFlag = false --记录断线重连标记 instance.re_maxResendTimes = 2 --最大断线重发次数,超过该时间则取消发送 instance.re_sendWaitTime = 0 --记录断线等待时间(秒) instance.re_maxSendWaitTime = 5 --消息断线重发等待时间(秒),超过该时间会重连 instance.ReconnectTime=0 -- 重连的发生时间 setmetatable(instance, Network) return instance end function Network:Start() UpdateBeat:Add(self.Update, self) end --卸载网络监听-- function Network:Unload() UpdateBeat:Remove(self.Update, self) end --当连接建立时-- function Network:OnConnect() self.isConnected = true self.bIsStartListenHeartBeat = true Game.GlobalEvent:DispatchEvent(Protocal.Connect, self) end --异常断线-- function Network:OnException() SysPanel.ShowOne(Language[12110], function() Game.Logout() end) self.bIsStartListenHeartBeat = false Game.GlobalEvent:DispatchEvent(Protocal.Exception, self) end --连接中断,或者被踢掉-- function Network:OnDisconnect(err) self.reconnectFlag = true self.isConnected = false self.bIsStartListenHeartBeat = false Game.GlobalEvent:DispatchEvent(Protocal.Disconnect, self) RequestPanel.Show(Language[12111])--..err) self.socket:TryReconnect() self.ReconnectTime= Time.time end function Network:SendClientHeartBeat() --Log("-------SendClientHeartBeat-----") self.socket:SendHeartBeat() end function Network:ReceiveClientHeartBeat(buffer) local time = buffer:ReadIntToByte() -- Log("-------ReceiveClientHeartBeat----- time: "..time) Game.GlobalEvent:DispatchEvent(GameEvent.Network.OnReceiveHeartBeat, self, time) end --重新建立socket连接,回调lua方法 function Network:OnReconnect() RequestPanel.Hide() RequestPanel.Show(Language[12112]) self.re_resendTimes = 0 self.reconnectFlag = false self.socket:SendMessageWithCallBack(MessageTypeProto_pb.RECONNECT_REQUEST, MessageTypeProto_pb.RECONNECT_RESPONSE, nil, function(b) Log("已经重连!!") RequestPanel.Hide() self.isConnected = true self.bIsStartListenHeartBeat = true Game.GlobalEvent:DispatchEvent(Protocal.Connect, self) end) coroutine.start(function() coroutine.wait(2) if not self.isConnected then Log("没有收到 重连信息,重新设置链接!!") self.socket:Disconnect("no reconnect msg, reset socket!!") end end) end function Network:Reset() self.isConnected = false self.re_resendTimes = 0 self.reconnectFlag = false end function Network:OnConnectFail() RequestPanel.Hide() SysPanel.ShowOne(Language[12113]) end --重连3次失败 function Network:OnReconnectFail() -- 重连时间超过2分钟强制回到登录界面 if Time.time - self.ReconnectTime > 60 then --SysPanel.ShowTwo(Language[12235], function() Game.Logout() --end, Language[12117]) end self.re_resendTimes = self.re_resendTimes + 1 if self.re_resendTimes > self.re_maxResendTimes then RequestPanel.Hide() SysPanel.ShowTwo(Language[12114], function() Game.Logout() end, function() if self.isConnected then PopupTipPanel.ShowTip(Language[12115]) else RequestPanel.Show(Language[12116]) self.re_sendWaitTime = 0 self.re_resendTimes = 0 end end, Language[12117]) end end -- 发送消息 function Network:SendMessage(nMsgId, sMsg) local buffer = ByteBuffer.New() if sMsg then buffer:WriteBuffer(sMsg) end MyPCall(function() self.socket:SendMessage(nMsgId, buffer) end) end function Network:SendMessageWithCallBack(nMsgId, nReMsgId, sMsg, func, isHideMask) if not isHideMask then RequestPanel.Show(Language[12118]) end self.sendFuncQueue:Enqueue(function() local buffer = ByteBuffer.New() if sMsg then buffer:WriteBuffer(sMsg) end self:SetSending(true) self.sendWaitTime = 0 if not isHideMask then RequestPanel.Show(self.resendTimes > 0 and Language[12119] or Language[12118]) end --Log("-------SendMessage-----msgId:"..nMsgId) self.socket:SendMessageWithCallBack(nMsgId, nReMsgId, buffer, function(b) --Log("-------ReceiveMessage-----msgId:"..nReMsgId) self:SetSending(false) self.resendTimes = 0 if self.sendFuncQueue.size > 0 then self.sendFuncQueue:Dequeue() end --waitingTimes = 0 if func then func(b) end if not isHideMask then --该参数为空时,会在请求时显示全屏遮罩,防止误点击 RequestPanel.Hide() end end) end) end function Network:ReceiveErrorInfo(buffer) local data = buffer:DataByte() local msg = CommonProto_pb.ErrorResponse() msg:ParseFromString(data) self:SetSending(false) self.resendTimes = 0 if self.sendFuncQueue.size > 0 then self.sendFuncQueue:Dequeue() end --waitingTimes = 0 RequestPanel.Hide() -- 登录过程中报错 LoadingPanel.ErrorStep(msg) LogError("Network ReceiveErrorInfo errCode:"..msg.errCode) --Log("msg.errCode:" .. msg.errCode) --Log("msg.errMsg:" .. msg.errMsg) --for i=1,#msg.errParams do -- Log("msg.errParams:" .. msg.errParams[i]) --end if (msg.errCode == 20000) then if (msg.errMsg == Language[11507]) then IndicationManager.canPopUpBagMaxMessage = true elseif (msg.errMsg == Language[11508]) then IndicationManager.getRewardFromMailMessage = true else PopupTipPanel.ShowTip(msg.errMsg) end return end if msg.errCode == -1 then LogError("Network ReceiveErrorInfo errDes:"..msg.errMsg) end local desc, title = self:GetErrorTip(msg) if msg.errCode == -101 or msg.errCode == -102 or msg.errCode == -103 then if(Time.time- self.ReconnectTime<10)then return end --被顶号或者被封号 Game.Logout() AppConst.Code = desc--TODO:重登会重置所有lua变量信息,用一个不用的C#变量记录,用于记录异常退出信息 return end if desc then if title then SysPanel.ShowOne(desc, nil, nil, title) else PopupTipPanel.ShowTip(desc) end else PopupTipPanel.ShowTip(msg.errMsg) end end function Network:GetErrorTip(msg) local errorCfg = ConfigManager.TryGetConfigData(ConfigName.ErrorCodeHint, msg.errCode) if errorCfg then local params = {} for i = 1, #msg.errParams do table.insert(params, GetLanguageStrById(msg.errParams[i])) end if errorCfg.ShowType == 1 then --tips return string.format(GetLanguageStrById(errorCfg.Desc), unpack(params)) elseif errorCfg.ShowType == 2 then --弹窗 local contexts = string.split(GetLanguageStrById(errorCfg.Desc), "#") --标题#内容 return string.format(contexts[2], unpack(params)), contexts[1] end end return msg.errMsg end --注册消息模块 function Network:RegisterMessage(nMsgId, pMessageHandle) self.socket:RegistNetMessage(nMsgId, pMessageHandle) end function Network:UnRegisterMessage(nMsgId, pMessageHandle) self.socket:UnregistNetMessage(nMsgId, pMessageHandle) end -- 设置发送状态 function Network:SetSending(isSending) self.sendFlag = isSending end function Network:IsSending() return self.sendFlag end function Network:Update() if self.reconnectFlag and self.re_resendTimes <= self.re_maxResendTimes then self.re_sendWaitTime = self.re_sendWaitTime + Time.fixedDeltaTime if self.re_sendWaitTime > self.re_maxSendWaitTime then RequestPanel.Show(Language[12120]) self.socket:TryReconnect() self.re_sendWaitTime = 0 end end if not self.isConnected then return end local dt = Time.fixedDeltaTime if self.bIsStartListenHeartBeat then self.waitingTimes = self.waitingTimes + dt if self.waitingTimes > self.maxWaitingTimes then self:SendClientHeartBeat() self.waitingTimes = 0 end end if self:IsSending() then self.sendWaitTime = self.sendWaitTime + dt if self.sendWaitTime > self.maxSendWaitTime then if self.resendTimes < self.maxResendTimes then --logError("重发次数 :: " .. self.resendTimes) MyPCall(self.sendFunc) elseif self.resendTimes == self.maxResendTimes then RequestPanel.Hide() -- SysPanel.ShowTwo(Language[12121], function() -- Game.Logout() -- end, function() -- -- if self:IsSending() then -- self:SetSending(false) -- self.resendTimes = 0 -- self.sendFuncQueue:Clear() -- -- end -- end, Language[12117]) Game.Logout() end self.resendTimes = self.resendTimes + 1 end else if self.sendFuncQueue.size > 0 then self.sendFunc = self.sendFuncQueue:Peek() MyPCall(self.sendFunc) end end end