加速器是网页类游戏常使用的通过修改前端帧频率来达到加速操作目的的工具,常用的有游戏浏览器等。所以前端的时间会变得很快或者很慢(跟后端的比较)。
防加速器设计上:
在网关服务器里限制连接发来(客户端发来)的移动系统里的角色移动消息,
根据消息的时间戳跟服务器的时间相比,时间相差较大就踢掉.前后端需要在一定时间内同步一次
时间上,每60秒同步一次后端时间到前端,设定为加速不超过9秒(9/60 ,即加速15%),减速不超过15秒(15/60,即减速25%,因为有网络延时,所以减速的会放宽些)。
本文代码内容如下:
网关连接处理客户端的移动消息
bool gateway_session::msgParse(const MSG::base_msg *ptNull, const unsigned int msglen)
{
...
case MOVE_USERCMD://移动指令
{
if (!testRunState(gateway_session::RunState_Play))
{
return true;
}
PRINT_MSG_LOG(ptrMsg, 0);
switch (ptrMsg->second)
{
case USERMOVE_MOVE_USERCMD_PARA_C:
{
if(msglen != sizeof(stplayerMoveUpMoveplayerCmd))
{
g_log->error("消息长度有误:%u,%u",this->id,msglen);
return false;
}
MSG::stplayerMoveUpMoveplayerCmd send = *(MSG::stplayerMoveUpMoveplayerCmd*) ptrMsg;
int timeDiff = int((int)send.dwTimestamp - (int)main_logic_thread::currentTime.sec());
if (timeDiff > 9 || timeDiff < -15)//相差时间过大则断开网关的客户端连接(单位秒)
{
error_log("加速器:时间相差过大(%u,%llu),(帐号%s,角色(%u,%s),ip:%s)",
send.dwTimestamp,main_logic_thread::currentTime.sec(),
account,pplayer->id,pplayer->name,getIP());
TerminateWait();
return false;
}
return forwardScene(&send, sizeof(send));
}
break;
...
}
...
}
...
}
前后端需要在一定时间内同步一次
//发送同步时间消息
struct gateway_session_time_sync: public callback<gateway_session>
{
bool invoke(gateway_session *entry)
{
MSG::stGameTimeTimerplayerCmd cmd;
cmd.qwGameTime = (uint32)(main_logic_thread::currentTime.sec());
entry->sendmsg(&cmd,sizeof(cmd));
return true;
}
}timesync;
主线程循环定时同步后端时间到所有连接的前端
void main_logic_thread::run()
{
while(!isFinal())
{
setRunning();
main_logic_thread::currentTime.now();
thread_base::msleep(50);
g_server.handle_msg();
if(_one_sec(main_logic_thread::currentTime))
{
g_gateway_session_manager.invoke_all_task(timeout);
if(_one_min(main_logic_thread::currentTime))
{
g_gateway_session_manager.invoke_all_task(timesync);
}
...
}