public void OnClientHeart(GameClient client, long reportRealClientTick) { if (client != null) { if (!client.ClientSocket.session.IsGM) { lock (this.Mutex) { SpeedUpTickCheck.CheckRoleItem roleItem = null; if (!this.checkRoleDict.TryGetValue(client.ClientData.RoleID, out roleItem)) { roleItem = new SpeedUpTickCheck.CheckRoleItem(); roleItem.RoleId = client.ClientData.RoleID; roleItem.RoleName = client.ClientData.RoleName; roleItem.UserId = client.strUserID; roleItem.IpAndPort = RobotTaskValidator.getInstance().GetIp(client); roleItem.LastReportClientTick = reportRealClientTick; roleItem.LastReceiveServerMs = TimeUtil.timeGetTime(); roleItem.MaybeTroubleTimes = 0; roleItem.MaybeTroubleDiffRates.Clear(); roleItem.CliTotalElapsedTicks = 0L; roleItem.SrvTotalElapsedTicks = 0L; roleItem.TotalElapsedTimes = 0; this.checkRoleDict[client.ClientData.RoleID] = roleItem; } else { long _LastReportClientTick = roleItem.LastReportClientTick; uint _LastReceiveServerMs = roleItem.LastReceiveServerMs; roleItem.LastReportClientTick = reportRealClientTick; roleItem.LastReceiveServerMs = TimeUtil.timeGetTime(); uint serverDiffMs = roleItem.LastReceiveServerMs - _LastReceiveServerMs; long serverDiffTick = (long)((ulong)serverDiffMs * 10000UL); long clientDiffTick = roleItem.LastReportClientTick - _LastReportClientTick; if (serverDiffTick > 0L) { double pipeTickDiffRate = (double)Math.Abs(serverDiffTick - clientDiffTick) * 1.0 / (double)serverDiffTick; if (pipeTickDiffRate > this.currUseDiffRate) { roleItem.MaybeTroubleTimes++; roleItem.MaybeTroubleDiffRates.Add(pipeTickDiffRate); if (roleItem.MaybeTroubleTimes >= 5) { long lastLog1Tick = 0L; if (!this.roleLastLog1Ticks.TryGetValue(roleItem.RoleId, out lastLog1Tick) || TimeUtil.NowDateTime().Ticks - lastLog1Tick >= 7200000000L) { this.roleLastLog1Ticks[roleItem.RoleId] = TimeUtil.NowDateTime().Ticks; LogManager.WriteLog(LogTypes.Fatal, string.Format("Check1 uid={0},rid={1},rname={2},ip={3} 疑似使用加速, 心跳时间差比例={4}", new object[] { roleItem.UserId, roleItem.RoleId, roleItem.RoleName, roleItem.IpAndPort, string.Join <double>(",", roleItem.MaybeTroubleDiffRates) }), null, false); } roleItem.MaybeTroubleTimes = 0; roleItem.MaybeTroubleDiffRates.Clear(); } } else if (Global.GetRandom() > 0.6) { this.totalDiffRate += pipeTickDiffRate; this.totalDiffCnt += 1.0; if (this.totalDiffCnt >= 100.0) { double oldDiffRate = this.currUseDiffRate; this.currUseDiffRate = this.totalDiffRate / this.totalDiffCnt; this.totalDiffCnt = 0.0; LogManager.WriteLog(LogTypes.Error, string.Format("加速时间允许时间差范围变更 {0} ---> {1}", oldDiffRate, this.currUseDiffRate), null, true); } } roleItem.CliTotalElapsedTicks += clientDiffTick; roleItem.SrvTotalElapsedTicks += serverDiffTick; roleItem.TotalElapsedTimes++; if (roleItem.TotalElapsedTimes >= this.TotalElapsedTimes) { double _rate = (double)Math.Abs(roleItem.SrvTotalElapsedTicks - roleItem.CliTotalElapsedTicks) * 1.0 / (double)roleItem.SrvTotalElapsedTicks; if (_rate > this.TotalElapsedDiffRate) { long lastLog2Tick = 0L; if (!this.roleLastLog2Ticks.TryGetValue(roleItem.RoleId, out lastLog2Tick) || TimeUtil.NowDateTime().Ticks - lastLog2Tick >= 7200000000L) { this.roleLastLog2Ticks[roleItem.RoleId] = TimeUtil.NowDateTime().Ticks; LogManager.WriteLog(LogTypes.Fatal, string.Format("Check2 uid={0},rid={1},rname={2},ip={3} 疑似使用加速, CliTotalElapsedTicks={4}, SrvTotalElapsedTicks={5}, diffRate={6}", new object[] { roleItem.UserId, roleItem.RoleId, roleItem.RoleName, roleItem.IpAndPort, roleItem.CliTotalElapsedTicks, roleItem.SrvTotalElapsedTicks, _rate }), null, false); } } roleItem.CliTotalElapsedTicks = 0L; roleItem.SrvTotalElapsedTicks = 0L; roleItem.TotalElapsedTimes = 0; } } } } } } }
public void OnClientHeart(GameClient client, long reportRealClientTick) { if (client == null) { return; } if (client.ClientSocket.session.IsGM) { return; } lock (Mutex) { CheckRoleItem roleItem = null; if (!checkRoleDict.TryGetValue(client.ClientData.RoleID, out roleItem)) { roleItem = new CheckRoleItem(); roleItem.RoleId = client.ClientData.RoleID; roleItem.RoleName = client.ClientData.RoleName; roleItem.UserId = client.strUserID; roleItem.IpAndPort = RobotTaskValidator.getInstance().GetIp(client); roleItem.LastReportClientTick = reportRealClientTick; roleItem.LastReceiveServerMs = TimeUtil.timeGetTime(); #region Check1 roleItem.MaybeTroubleTimes = 0; roleItem.MaybeTroubleDiffRates.Clear(); #endregion #region Check2 roleItem.CliTotalElapsedTicks = 0; roleItem.SrvTotalElapsedTicks = 0; roleItem.TotalElapsedTimes = 0; #endregion checkRoleDict[client.ClientData.RoleID] = roleItem; } else { long _LastReportClientTick = roleItem.LastReportClientTick; uint _LastReceiveServerMs = roleItem.LastReceiveServerMs; roleItem.LastReportClientTick = reportRealClientTick; roleItem.LastReceiveServerMs = TimeUtil.timeGetTime(); uint serverDiffMs = roleItem.LastReceiveServerMs - _LastReceiveServerMs; long serverDiffTick = ((long)serverDiffMs) * TimeSpan.TicksPerMillisecond; long clientDiffTick = roleItem.LastReportClientTick - _LastReportClientTick; if (serverDiffTick <= 0) { return; //wtf } #region Check1 double pipeTickDiffRate = Math.Abs(serverDiffTick - clientDiffTick) * 1.0 / serverDiffTick; if (pipeTickDiffRate > currUseDiffRate) { roleItem.MaybeTroubleTimes++; roleItem.MaybeTroubleDiffRates.Add(pipeTickDiffRate); if (roleItem.MaybeTroubleTimes >= 5) { long lastLog1Tick = 0; if (!roleLastLog1Ticks.TryGetValue(roleItem.RoleId, out lastLog1Tick) || TimeUtil.NowDateTime().Ticks - lastLog1Tick >= 12 * TimeSpan.TicksPerMinute) { roleLastLog1Ticks[roleItem.RoleId] = TimeUtil.NowDateTime().Ticks; LogManager.WriteLog(LogTypes.Fatal, string.Format("Check1 uid={0},rid={1},rname={2},ip={3} 疑似使用加速, 心跳时间差比例={4}", roleItem.UserId, roleItem.RoleId, roleItem.RoleName, roleItem.IpAndPort, string.Join(",", roleItem.MaybeTroubleDiffRates)), null, false); } roleItem.MaybeTroubleTimes = 0; roleItem.MaybeTroubleDiffRates.Clear(); } } else { // 在有效的时间差范围内, 有40%的概率统计本次时间差,用于逐步修正服务器的正确时间差范围 if (Global.GetRandom() > 0.6) { totalDiffRate += pipeTickDiffRate; totalDiffCnt++; if (totalDiffCnt >= 100) { // 每统计100次,校正一下时间差 double oldDiffRate = currUseDiffRate; currUseDiffRate = totalDiffRate / totalDiffCnt; totalDiffCnt = 0; LogManager.WriteLog(LogTypes.Error, string.Format("加速时间允许时间差范围变更 {0} ---> {1}", oldDiffRate, currUseDiffRate)); } } } #endregion #region Check2 roleItem.CliTotalElapsedTicks += clientDiffTick; roleItem.SrvTotalElapsedTicks += serverDiffTick; roleItem.TotalElapsedTimes++; if (roleItem.TotalElapsedTimes >= this.TotalElapsedTimes) { double _rate = Math.Abs(roleItem.SrvTotalElapsedTicks - roleItem.CliTotalElapsedTicks) * 1.0 / roleItem.SrvTotalElapsedTicks; if (_rate > this.TotalElapsedDiffRate) { long lastLog2Tick = 0; if (!roleLastLog2Ticks.TryGetValue(roleItem.RoleId, out lastLog2Tick) || TimeUtil.NowDateTime().Ticks - lastLog2Tick >= 12 * TimeSpan.TicksPerMinute) { roleLastLog2Ticks[roleItem.RoleId] = TimeUtil.NowDateTime().Ticks; LogManager.WriteLog(LogTypes.Fatal, string.Format("Check2 uid={0},rid={1},rname={2},ip={3} 疑似使用加速, CliTotalElapsedTicks={4}, SrvTotalElapsedTicks={5}, diffRate={6}", roleItem.UserId, roleItem.RoleId, roleItem.RoleName, roleItem.IpAndPort, roleItem.CliTotalElapsedTicks, roleItem.SrvTotalElapsedTicks, _rate), null, false); } } roleItem.CliTotalElapsedTicks = 0; roleItem.SrvTotalElapsedTicks = 0; roleItem.TotalElapsedTimes = 0; } #endregion } } }