예제 #1
0
 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;
                         }
                     }
                 }
             }
         }
     }
 }
예제 #2
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
                }
            }
        }