玩家下线,之前一直感觉这个过程有点复杂
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部分)的更多相关文章

  1. GS踢玩家下线功能

    GS踢玩家下线功能 //key:userId, val:nChannelId (当前在线用户) std::map<int, int> m_mapOnLineUserByUid; ///&l ...

  2. GS LiveMgr心跳管理类

    struct LiveMgr { private: int m_nCount; ///< 管理数量 std::vector<int> m_vecChannels; ///< 所 ...

  3. GS与网络打交道

    与网络打交道 在GS,GC,Share都与网络打交道,但还是GC最多 GC打交道过程 send_stat BaseChannel::SendCmdTry() { if (!m_queCmd.size( ...

  4. GS与数据库打交道

    GS与数据库打交道 link_stat stat = (link_stat)rPkt.size; if (stat == link_stat::link_connected) { GameChanne ...

  5. 再看GS线程

    再看GS线程 void GameServer::ProcessThreadTry() { ; packet rcvPkt; rcvPkt.data = * ]; //该事件工厂主要创建了两个定时器1. ...

  6. share干什么的

    share到底干什么的 //--------------------打开GameServer,share中加载------------------------- .加载nBodyID //玩家的nBo ...

  7. 项目分析(map复习)

    有段时间没看map里面的东西了,刚才看发现功能上增加了一些,在来复习了一次流程初始化每个map建立线程,这个线程有两个功能,1.处理GS发过来的包 2.驱动map里面的定时器GS发过来的包是存在m_g ...

  8. mmzb游戏事故分析

    最近一次线上更新,老项目挂了,遍地哀嚎,日活跃掉了好多,心痛... 这次维护时,SA为了缩减硬件资源,做了一次数据库迁移.给到开发手上的player db,只有一些索引数据,不带有任一玩家数据.玩家上 ...

  9. bigworld源码分析(3)——dbMgr分析

    dbMgr主要是玩家数据的读取和保存的,例如在bigworld源码分析(3)中,玩家在认证的时候,loginApp需要通过dbMgr来验证玩家数据是否合法,这就是针对玩家的账号数据进行查询.本篇中,我 ...

随机推荐

  1. windows下apache+php配置 问题总结

    以下为转帖内容: 原文出处:http://www.cnblogs.com/angelox/archive/2008/10/09/1306732.html PHP5+APACHE2.2配置成功案例:第一 ...

  2. Oracle SID爆破工具SidGuess

    Oracle SID爆破工具SidGuess   在Oracle中,SID是System IDentifier的缩写.SID是一个数据库的唯一标识符.当用户希望远程连接Oracle数据库时,则需要知道 ...

  3. 苹果放宽了 iOS 5.0 对应用本地存储的限制

    iOS5.0引入了iCloud,让那些需要本地存储较多数据的app开发者(比如支持离线的杂志,新闻类app)陷入了 尴尬的境地,因为将大量数据存储在/Documents 文件夹将导致iCloud同步变 ...

  4. 学习和家庭教育 z

    大家好,我是王宁. 今天能站在这里,纯属偶然. 为什么说偶然呢? 因为,南雅是个人才济济的地方,164班是一个优秀的集体. 个人认为,班级前二十几名的同学,时机适宜,谁考班上第一名都有可能. 妈妈对我 ...

  5. wpa破解学习

    TENDA  159031106A iPhone 192.168.0.11 90:27:E4:53:49:D6 18:58:52 PC-201211262044 192.168.0.12 00:F1: ...

  6. hdu4493(C++)

    //卡格式的题目 #include<iostream> #include<iomanip>using namespace std;int main(){ int T,i; do ...

  7. 【好】Paxos以及分布式一致性的学习

    Paxos,一言以蔽之,我们需要一种提交协议来确保分布式系统中的全局操作即使是在发生故障的情况下也能保证正确性. 跟拜占庭将军问题是不同的问题,虽然拜占庭也是Lamport提出的.拜占庭里面有叛徒,有 ...

  8. 【VBS】检索Outlook本地邮箱

    实现功能:使用VBS检索Outlook本地邮箱中,今天是否收到某标题的邮件. 代码如下: ' yyyy-m-d 0:00 AM ' yyyy-m-d 11:59 PM Function CheckMa ...

  9. window.location.href重定向 不会触发webview

    通过window.location.href来重定向的,安卓不会触发shouldOverrideUrlLoading.

  10. Android使用OKHttp3实现下载(断点续传、显示运行进度)

    OKHttp3是现在很流行的Android网络请求框架,那么怎样利用Android实现断点续传呢,今天写了个Demo尝试了一下,感觉还是有点意思 准备阶段 我们会用到OKHttp3来做网络请求,使用R ...