玩家下线(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来验证玩家数据是否合法,这就是针对玩家的账号数据进行查询.本篇中,我 ...
随机推荐
- 524. Longest Word in Dictionary through Deleting
Given a string and a string dictionary, find the longest string in the dictionary that can be formed ...
- hdu 4738 无向图缩点断桥 // 细节坑题
Caocao's Bridges 题意:给个无向图,求出边权最小的桥. 一看,直接缩点,若无桥,输出-1,有桥,遍历下边,更新最小..分分钟搞定,以为IA的..一交wa... 坑点:1:若原图不连通, ...
- 前端优化之Combo Handler
Combo Handler来合并CSS/JS文件 背景 Combo Handler是Yahoo!开发的一个Apache模块,它实现了开发人员简单方便地通过URL来合并JavaScript和CSS文件, ...
- 联通积分兑换的Q币怎么兑换到QQ上
可登录联通积分商城http://jf.10010.com 查询和兑换Q币, 1,通过联通积分商城自主兑换,提交订单扣除积分成功后,10010端口将自动为您下发验证码短信. 2,在有效期内登陆Q币充值 ...
- AC日记——营业额统计 codevs 1296 (splay版)
营业额统计 思路: 每次,插入一个点: 然后找前驱后继: 来,上代码: #include <cmath> #include <cstdio> #include <iost ...
- react 使用antd的多选功能做一个单选与全选效果
一个小而简单的单选全选功能,其实官网已经给出效果了,不过是我多做了些复合用法 addorupdatemodal.jsx import React from "react"; imp ...
- 牛客网 牛客小白月赛1 E.圆与三角形-公式题
E.圆与三角形 链接:https://www.nowcoder.com/acm/contest/85/E来源:牛客网 这个题把公式推一下, 发现就是1+sinA*r,sinA最大为1,所以 ...
- fiddle-获取 Cookie 信息
随着网络安全(例如:登录安全等)要求的不断提升,越来越多的登录应用在登录时添加了验证码登录,而验证码生成算法也在不断的进化,因而对含登录态的自动化测试脚本运行造成了一定程度的困扰,目前解决此种问题的方 ...
- 洛谷—— P1609 最小回文数
https://www.luogu.org/problemnew/show/1609 题目描述 回文数是从左向右读和从右向左读结果一样的数字串. 例如:121.44 和3是回文数,175和36不是. ...
- 洛谷——P1962 斐波那契数列
P1962 斐波那契数列 题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 ...