|
- local Heart = class("Heart" , require("luaScript.Protocol.Protocol"))
-
-
- local HeartCmd = {
-
- --[[
- * 心跳包
- * <pre>
- * 请求: {@link HeartBeatRequest}
- * 响应: {@link HeartBeatResponse}
- * </pre>
- --]]
- HEART_BEAT = 0x2008,
- }
-
- -- 服务器返回的心跳包
- local HeartBeatResponse = defClass("HeartBeatResponse"
- -- 服务器的当前时间,从1970开始的毫秒数
- , defVar("serverTime", VT_Long, 0)
- )
-
-
- -- 每隔多久发一次心跳包
- local HeartBeatTime = 5
-
- -- 心跳包多久没有收到就认为超时了
- local NetOverTime = 8;
-
- function Heart:onLoginToUserProtocol()
-
- logD("Heart:onLoginToUserProtocol()")
-
- -- 开始发送心跳包
- self.net.Socket:setOption("HeartBeatCode" , HeartCmd.HEART_BEAT);
- self.net.Socket:setOption("HeartBeatTime" , HeartBeatTime * 1000);
-
- self:resetNetOverTimer();
- end
-
- -- 服务器心跳回调
- function Heart:onUpdateServerTime(status, response)
-
- logD("Heart:onUpdateServerTime()")
-
- if status ~= 0 then
- print("心跳包返回错误代码 statusCode:" .. tostring(status))
- return;
- end;
-
- -- 更新
- self.heartBeatResponse = response:updateTo(self.heartBeatResponse);
- self.TimeEclipsed = response.serverTime / 1000;
- self.TimeStart = os.time();
- -- 记录下上次消息时间
- self.LastNetMessageTime = self.TimeStart;
- self:resetNetOverTimer()
- end
-
- function Heart:onNetProcessMessage(event)
- self.LastNetMessageTime = os.time();
- end
-
- -- 设置超时定时器
- function Heart:resetNetOverTimer()
- logD("Heart:resetNetOverTimer()")
-
- if not tolua.isnull(self.TimeoutAction) then
- app.mainScene:stopAction(self.TimeoutAction);
- end
- self.TimeoutAction = nil;
- self.NeedToReconnect = false;
-
- if app.mainScene then
- local t1 = os.time()
-
- local function onTimeout()
-
- logD("Heart:resetNetOverTimer() 心跳超时时间 = ", os.time())
- logD("Heart:resetNetOverTimer() 误差超时时间 = ", (os.time()-t1))
-
- -- 两帧之后,再检查是否有收到消息,如果还没收到,就认为超时
- local lastTime = self.LastNetMessageTime;
- local curTime = os.time();
- local deltaTime = curTime - lastTime;
- logD("Heart:resetNetOverTimer() curTime = ", curTime);
- logD("Heart:resetNetOverTimer() lastTime = ", lastTime);
- logD("Heart:resetNetOverTimer() deltaTime = ", deltaTime);
-
- if deltaTime >= NetOverTime then
- -- 这里不一定是断线了,如果充值的时候,游戏渲染窗口就不渲染了整个游戏就更新了,网络消息也不会触发脚本了
- -- 但是这个时候网络其实是没有断开的
- -- 延迟一帧执行,给一次机会
- local function reconnectToServer()
- if self.NeedToReconnect and not app.user.kickOffState then
- logD("Heart:resetNetOverTimer() 已经[" .. deltaTime .. "]秒没有收到服务器消息了,说明网络有问题,重连咯");
- -- 断开网络后 会自动重连 不需要手动调用reconnect
- self.net:close();
- -- 马上重连
- --self.net:reConnect();
- self.NeedToReconnect = false
- end
- end
- self.NeedToReconnect = true
- runInNextFrame(reconnectToServer)
- else
- -- 说明在定时器期间又收到服务器的消息但没有收到心跳包
- -- 再给一次机会,不要断线
- runInNextFrame(function()
- self:resetNetOverTimer()
- end)
- end
- self.TimeoutAction = nil;
- end
- logD("Heart:resetNetOverTimer() 心跳开始本地时间 = ", t1);
- -- 发完心跳包一段时间后还没有新消息,就说明网络死了
- self.TimeoutAction = app.mainScene:runActions(cc.DelayTime:create(NetOverTime), onTimeout);
- end
- end
-
- -- 停止
- function Heart:stop()
-
- end
-
- -- 服务器时间(返回秒数)
- function Heart:getServerTime()
- local now = os.time()
- local seconds = now - self.TimeStart;
- return math.ceil(self.TimeEclipsed + seconds);
- end
-
- -- 服务器时间(日期形式返回)
- function Heart:getServerDateTime()
- return BeijingTime.dateFunc(self:getServerTime())
- end
-
- --知道已经断开连接停止检测
- function Heart:onStopHeart()
- if not tolua.isnull(self.TimeoutAction) then
- app.mainScene:stopAction(self.TimeoutAction);
- end
- end
-
- function Heart:ctor(net)
- Heart.super.ctor(self , net);
- self.heartBeatResponse = HeartBeatResponse:new();
- -- 上次心跳包服务器时间
- self.TimeEclipsed = 0;
- -- 上次心跳包客户端时间
- self.TimeStart = 0;
- -- 上次更新消息时间
- self.LastNetMessageTime = 0
- -- 注册网络消息更新事件
- app:addEventListener("onRecvMsgFromGameServer" , handler(self , self.onNetProcessMessage));
- -- 注册登录事件
- app:addEventListener("onGameServerConnected" , handler(self , self.onLoginToUserProtocol));
-
- app:addEventListener("onGameServerDisConnect" , handler(self , self.onStopHeart));
-
-
- -- 注册心跳回调函数
- self:defPullMsg{name = "heartBeat", cmd = HeartCmd.HEART_BEAT , resCmd = HeartCmd.HEART_BEAT, reader = HeartBeatResponse , func = handler(self , self.onUpdateServerTime)};
- self:defPushMsg{cmd = HeartCmd.HEART_BEAT , reader = HeartBeatResponse , func = handler(self , self.onUpdateServerTime)};
- end
-
- return Heart;
|