玩家下线(GS部分)
玩家下线,之前一直感觉这个过程有点复杂
else if (stat == link_stat::link_disconnected || stat == link_stat::link_connect_failed )
{
GameChannel* pDisconnectGC = m_vecChannel[rPkt.channel_id];
if(pDisconnectGC)
{
//如果进入了地图,保存人物信息时会调用push_freeQueue + 滞空m_Channels[channel_id],
pDisconnectGC->OnDisconnect();//下线的一些收尾工作 //如果未进地图就下线,直接断开;不用保存角色详细数据,可直接放入释放队列中
if(!pDisconnectGC->m_pMap)
{
//PushFreeQueue(pDisconnectGC);
//m_vecChannel[rPkt.channel_id] = NULL;
AutoFreeGC(pDisconnectGC);
}
}
m_LiveMgr.Remove(rPkt.channel_id);//将livemgr的这个位置清零
}
下面一步一步看这个过程
bool GameChannel::OnDisconnect()
{
//m_isDisconnect = true;
OnOffLine();
return true;
} void GameChannel::OnOffLine()
{
switch (m_eGameState)
{
case eGameState_Login://登录状态
ClearLoginRcd();//清除登录状态:主要是删除已删除的角色,删除在线用户
break;
case eGameState_EnterMap://进入地图状态
ClearMapRcd();//从map下线,这个获取后面看
ClearLoginRcd();//清除登录状态
break;
case eGameState_InChangeMap:
//...正在切图就下线了,是不是该延时下线呢?
m_eGameState = eGameState_DelayDisconnect;
case eGameState_OnlyConnect: //未登陆,空连接
case eGameState_Disconnect: //已离线
return;
default:
break;
}
m_eGameState = eGameState_Disconnect;//将状态切换成离线状态
} void GameServer::AutoFreeGC(GameChannel* pGameChannel)
{
m_vecChannel[pGameChannel->m_nChannelId] = NULL;
//channel里面有个m_uDBGetAskRefCount,由于判断数据库是否有返回,加入数据库很慢的时候玩家下线你把这个内存释放了,等数据库返回的时候就访问了野指针
if (pGameChannel->IsNoDBAsk())//没有数据库访问,可以安全的删除指针了
{
delete pGameChannel;//删除玩家指针
pGameChannel = nullptr;
}
else
{
PushFreeQueue(pGameChannel);//如果还有数据库访问,就将其放到释放队列中延迟释放
}
} void GameServer::PushFreeQueue(GameChannel* gc)
{
FreeChannel fch;
fch.m_pGameChannel = gc;
fch.m_uTime = GetTickCount();
m_FreeQueue.push(fch);
} //那这个队列到底什么时候释放的呢?
在主线程里面初始化了一个定时器
void GameServer::InitTimer()
{
I_TimerFactory* pTimeFactory = NEW(TimerFactory);
SetPlug("TimerFactory", pTimeFactory);
m_FreeQueueTimer.reset(pTimeFactory->createTimer());
m_FreeQueueTimer->regTimer(std::bind(&GameServer::FreeQueueTimer, this));
m_FreeQueueTimer->setInterval( * );//(30 * 1000);
m_FreeQueueTimer->start();
} //之前出现过,函数回调的时候出现错误,当时就是这个问题回调的时候玩家已经下线了,channel已经删除了
/**
* 方案一:不直接释放,延迟1分钟,保证数据库不再返回时再释放。(数据库太忙情况不安全,停用)
* 方案二:不直接释放,看GC标志是否无数据请求。
*/
void GameServer::FreeQueueTimer()
{
if(!m_FreeQueue.size())
return ; int now = GetTickCount();
for (;;)//每次释放完或者到有不能释放的为止
{
if(!m_FreeQueue.size())
return ;
FreeChannel tmpFreeChannel = m_FreeQueue.front();
//if(now - tmpFreeChannel.m_uTime > 60 * 1000)
if (tmpFreeChannel.m_pGameChannel->IsNoDBAsk())//等到数据库没有访问了再释放
{
delete tmpFreeChannel.m_pGameChannel;
m_FreeQueue.pop();
}
else
{
break;
}
}
}
玩家下线(GS部分)的更多相关文章
- GS踢玩家下线功能
GS踢玩家下线功能 //key:userId, val:nChannelId (当前在线用户) std::map<int, int> m_mapOnLineUserByUid; ///&l ...
- GS LiveMgr心跳管理类
struct LiveMgr { private: int m_nCount; ///< 管理数量 std::vector<int> m_vecChannels; ///< 所 ...
- GS与网络打交道
与网络打交道 在GS,GC,Share都与网络打交道,但还是GC最多 GC打交道过程 send_stat BaseChannel::SendCmdTry() { if (!m_queCmd.size( ...
- GS与数据库打交道
GS与数据库打交道 link_stat stat = (link_stat)rPkt.size; if (stat == link_stat::link_connected) { GameChanne ...
- 再看GS线程
再看GS线程 void GameServer::ProcessThreadTry() { ; packet rcvPkt; rcvPkt.data = * ]; //该事件工厂主要创建了两个定时器1. ...
- share干什么的
share到底干什么的 //--------------------打开GameServer,share中加载------------------------- .加载nBodyID //玩家的nBo ...
- 项目分析(map复习)
有段时间没看map里面的东西了,刚才看发现功能上增加了一些,在来复习了一次流程初始化每个map建立线程,这个线程有两个功能,1.处理GS发过来的包 2.驱动map里面的定时器GS发过来的包是存在m_g ...
- mmzb游戏事故分析
最近一次线上更新,老项目挂了,遍地哀嚎,日活跃掉了好多,心痛... 这次维护时,SA为了缩减硬件资源,做了一次数据库迁移.给到开发手上的player db,只有一些索引数据,不带有任一玩家数据.玩家上 ...
- bigworld源码分析(3)——dbMgr分析
dbMgr主要是玩家数据的读取和保存的,例如在bigworld源码分析(3)中,玩家在认证的时候,loginApp需要通过dbMgr来验证玩家数据是否合法,这就是针对玩家的账号数据进行查询.本篇中,我 ...
随机推荐
- Light oj 1233 - Coin Change (III) (背包优化)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1233 题目就不说明了. 背包的二进制优化,比如10可以表示为1 2 4 3,而 ...
- An Introduction to Reflection in C++
Apr 13, 2017 Stop me if you’ve heard this one before. You are working on a messaging middleware, a g ...
- ReactiveCocoa 迎接下一个更加美好的世界
什么是ReactiveCocoa 如果你有看Github的Trending Objective-C榜单,那你肯定是见过ReactiveCocoa了.如果你在weibo上关注唐巧.onevcat等国内一 ...
- 利用反编译学习Android
自从2014年底到2015年中,全民创业的热潮就已经席卷全国了,一大批新的创业公司在北上广萌芽,也造成了大量的开发人员需求.扯远了,今天不谈创业潮,聊聊如何通过反编译学习Android.本文只是个人对 ...
- QQ分享到电脑SDK bug
问题:当图文(图片+文字+url)混合分享到我的电脑时,就会出bug,只显示图片. 经过测试: params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL," ...
- VIM正则表达式查找替换
0. 一些需要注意的不同 VIM中的正则表达式和其他的有点不一样 (1) 有些符号要用\转义,比如\+表示重复一次或以上,其他的还有一些,:h pattern查看(2) 非贪婪匹配用\{-}, 如 ...
- 【oracle ocp知识点一】
1.怎样确定数据库是否启动 su - oracle ps -ef |grep ora_|head -2 两种关系数据库是ora或者是自己主动存储管理的asm开头的, 查看进程能够知道数据库实例至少已经 ...
- Mysql processlist命令
Mysql processlist命令 mysqladmin -uroot -proot processlist mysql 查看当前连接数 命令: show processlist; 如果是ro ...
- Oracle的主键约束、唯一约束与外键约束
http://www.shangxueba.com/jingyan/122163.html主键: 1.主键约束: 一个表只能有一个主键约束.主键可以是单个字段,也可以是多个字段.无论是哪种情况,其所 ...
- CSS3进度条 和 HTML5 Canvas画圆环
看到一些高大上的进度条插件,然后想自己用CSS写.经过搜索资料之后,终于成功了.为了以后方便拿来用,或者复习.将代码贴出. HTML代码: 只需要两个div,外面的为一个有border的div id为 ...