Files
mir_server/server/SessionServer/SessionServer.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

1568 lines
39 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
CSessionServer::CSessionServer(CSSManager *lpSSManager)
:Inherited()
{
m_pSSManager = lpSSManager;
m_nDBClientCount = 0;
m_nEngineClientCount = 0;
m_dwCheckOnlineLogTick = 0;
m_boOnlineLoged = FALSE;
//m_isFcmOpen =false;
m_dwCheckOnlineLogTick =0;
m_dwSaveRankTick = _getTickCount() + SAVE_RANK_INTERVAL ; //下一次存盘的时间
m_SessionList.setLock(&m_SessionListLock);
SetServiceName(_T("会话"));
}
CSessionServer::~CSessionServer()
{
}
VOID CSessionServer::SendLogOnlineCount()
{
// OutputMsg(rmNormal,"SendLogOnlineCount start");
INT_PTR i;
INT nTotalUser;
CSessionClient *pClient;
LogSender *pLog = m_pSSManager->getLogClient();
if (NULL ==pLog) return;
nTotalUser = 0;
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
//如果连接对象是一个逻辑服务器
if ( pClient && pClient->connected() && pClient->registed()
&& pClient->getClientType() == GameServer && pClient->getClientServerIndex() > 0 )
{
//统计总人数
nTotalUser += pClient->m_nMaxUserCount;
//记录此服务器的在线人数
//报告这段时间最高在线
pLog->SendOnlineLog(pClient->getClientServerIndex(),pClient->m_nMaxUserCount);
//还原此服务器的最高在线人数
pClient->m_nMaxUserCount = pClient->m_nUserCount;
}
}
// OutputMsg(rmNormal,"SendLogOnlineCount end");
//向日志服务器发送记录所有服务器总在线人数的消息服务器ID值为0
//pLog->SendOnlineLog(0,nTotalUser);
}
typedef struct tagIpCount
{
long long lIp; //IP
long long nCount; //登陆的数目
} IPCOUNT;
//发送当前ip的状况
void CSessionServer::SendOnlineIpStatus()
{
PGAMESESSION *pSessionList;
CBaseList<IPCOUNT> ipList; //当前的ip的列表
pSessionList = m_SessionList;
INT_PTR i,j,k;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if(pSessionList[i]->nIsRawLogin ==0) continue; //是否在跨服登录
long long lIp = pSessionList[i]->nIPAddr; //当前的ip
bool flag=true;
for( j =ipList.count() -1; j >=0; --j )
{
if(ipList[j].lIp == lIp)
{
ipList[j].nCount ++;
//保持降序排列最前面的ip是最多的
//从队列的头开始找1个比这个个数小的进行交换
for(k = 0; k < j; k ++ )
{
if( ipList[k].nCount < ipList[j].nCount)
{
//先临时存起来
IPCOUNT temp;
temp.lIp = ipList[k].lIp;
temp.nCount= ipList[k].nCount;
ipList[k] = ipList[j]; //进行交换
ipList[j].lIp = temp.lIp;
ipList[j].nCount = temp.nCount;
break;
}
}
flag =false;
break;
}
}
//没有找到
if(flag)
{
IPCOUNT temp;
temp.lIp= lIp;
temp.nCount =1;
ipList.add(temp);
}
}
LogSender *pLog = m_pSSManager->getLogClient();
if (NULL ==pLog) return;
int nLogIpMinCount = m_pSSManager->GetIpLogCount(); //登陆了多少个账户就记录日志
INT_PTR nCount = ipList.count();
for(i= 0; i< nCount; i++ )
{
//如果少于这个数,就不记录了
if(ipList[i].nCount < nLogIpMinCount)
{
break;
}
else
{
//pLog->SetServerIndex(0); //设置服务器id0
pLog->SendLoginLog(ltHotIp ,(int)ipList[i].nCount,
"",inet_ntoa(*((in_addr*)&ipList[i].lIp)) ,"");
}
}
//上面已经对ip的数目列表进行了一次降序排列
}
//禁止ip并且封掉所有的账户
void CSessionServer::ForbidIpAndSealAll(long long lIP,bool bDirectSealIp )
{
return;
PGAMESESSION *pSessionList;
pSessionList = m_SessionList;
INT_PTR i;
bool sealAccount =false;
bool sealIp =false;
//bool isFirst =true;
int nTotalInterval = 0 ; //总间隔
TICKCOUNT nLastTick ;
INT_PTR nCount =0;
int nShortInterval =0; //间隔特别短的登陆比较多
char *sIp =inet_ntoa(*((in_addr*)&lIP)); //这个是IP
if(! bDirectSealIp )
{
int nForbidInterval = m_pSSManager->GetForbidInterval() * 1000; //获取间隔
int nKickCount = m_pSSManager->GetKickCount();
int nIpCount =0; //IP登陆的个数
int nLastInterval =0; //上1个间隔的
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
long long lAccountIp = pSessionList[i]->nIPAddr; //当前的ip
if(lAccountIp == lIP && pSessionList[i]->nIsRawLogin)
{
if (nIpCount >= 1)
{
int nInterval= (int)(pSessionList[i]->dwSessionTick -nLastTick); //间隔
if(nInterval <0)
{
nInterval = -nInterval;
}
if(nInterval <= nForbidInterval)
{
nCount ++; //间隔的个数
}
if(nIpCount >=2 )
{
int nNewInterval = nLastInterval - nInterval; //登陆的间隔差
if(nNewInterval <0)
{
nNewInterval = -nNewInterval;
}
if(nNewInterval < 3000) //间隔3秒登陆就有点问题
{
nShortInterval ++;
}
}
nLastInterval = nInterval;
}
nLastTick = pSessionList[i]->dwSessionTick; //上1次的间隔
nIpCount ++;
}
}
// //平均登陆的间隔少于一定的数
// if( nCount >= nKickCount || nShortInterval >= 7) //如果间隔小于这个数目,表示
// {
// INT_PTR nFirbidCount= GetIpForbidCount(lIP); //IP被封了多少次
// nFirbidCount ++;
// SetIpForbidCount(lIP,(int)nFirbidCount);
// OutputMsg(rmNormal,"Is Robot IP=%s,nCount=%d,nForbidInterval =%d, kickcount=%d,nShortInterval=%d,nFirbidCount=%d",sIp,nCount,nForbidInterval,nKickCount,nShortInterval,(int)nFirbidCount);
// //如果是第3次犯案
// if(nFirbidCount >=3 )
// {
// sealAccount =true;
// sealIp =true;
// }
// }
// else
// {
// OutputMsg(rmNormal,"MayBe Robot IP=%s,nCount=%d,nForbidInterval =%d ms, kickcount=%d",sIp,nCount,nForbidInterval,nKickCount);
// }
}
else
{
OutputMsg(rmNormal,"Seal account login IP=%s,Seal",sIp);
if (m_pSSManager->IsAutoSealIp())
{
sealIp =true;
}
}
//OutputMsg(rmNormal,"nForbidInterval =%d ms, kickcount=%d",nForbidInterval,nKickCount);
LogSender *pLog = m_pSSManager->getLogClient();
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( pSessionList[i]->nIPAddr == lIP )
{
OutputMsg(rmTip,"kick ip=%s,account=%s,serverindex=%d",sIp, pSessionList[i]->sAccount, (int)pSessionList[i]->nServerIndex); // 解封这个ip
if(sealAccount)
{
int nError = m_SQLConnection.Exec("update globaluser set passwd =\"@autoSeal\" where account=\"%s\"", pSessionList[i]->sAccount);
if(!nError)
{
m_SQLConnection.ResetQuery();
}
OutputMsg(rmTip,"Auto Seal account=%s,serverindex=%d",pSessionList[i]->sAccount, (int)pSessionList[i]->nServerIndex); // 解封这个ip
//封停账户
pLog->SendLoginLog(itSealAccount ,0,"", pSessionList[i]->sAccount ,"");
}
ProcessKickCrossActor((unsigned int)pSessionList[i]->nSessionID,pSessionList[i]->nServerIndex);
CloseSessionAtListIndex(i);
}
}
if(sealIp)
{
CBaseList<unsigned long long>& blackips= m_pSSManager->GetBlackIpList(); //获取黑名单列表
nCount = blackips.count();
bool flag =false;
for( i=0; i< nCount ;i++)
{
if(blackips[i] == lIP)
{
flag =true;
break;
}
}
if(!flag)
{
OutputMsg(rmTip,"Auto Seal ip=%s ",sIp); // 解封这个ip
blackips.add(lIP);
pLog->SendLoginLog(ltSealIp ,0,"",sIp ,"");
}
}
}
CCustomServerClientSocket* CSessionServer::CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn)
{
CSessionClient * pClient = new CSessionClient ;
pClient->SetClientSocket(nSocket, pAddrIn);
//CSessionClient(this, &m_SQLConnection, nSocket, pAddrIn);
pClient->SetParam(this,&m_SQLConnection,false);
return pClient;
}
VOID CSessionServer::ProcessClients()
{
INT_PTR i;
INT_PTR nDBCount = 0, nEngineCount = 0;
CSessionClient *pClient;
TICKCOUNT dwCurTick = _getTickCount();
//循环处理每个客户端连接
m_ClientList.flush();
//必须降序循环,因为列表中的数据可能在循环中被移除
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
//处理活动的连接
pClient->Run();
//删除断开的连接
if ( !pClient->connected() )
{
//连接在断开后的5分钟后删除
if ( dwCurTick - pClient->m_dwDisconnectedTick >= 5 * 60 * 1000 )
{
m_ClientList.lock();
m_ClientList.remove(i);
m_ClientList.unlock();
delete pClient;
}
continue;
}
//统计各个种类的客户端数量
if ( pClient->registed() )
{
if ( pClient->getClientType() == DBServer )
nDBCount++;
else if ( pClient->getClientType() == GameServer )
nEngineCount++;
}
}
m_nDBClientCount = nDBCount;
m_nEngineClientCount = nEngineCount;
}
BOOL CSessionServer::DoStart()
{
return TRUE;
}
VOID CSessionServer::DoStop()
{
}
VOID CSessionServer::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
INT_PTR nIndex;
PGAMESESSION pSession;
//OutputMsg( rmNormal, _T("DispatchInternalMessage MSGID=%d,PARAM1=%d,PARAM2=%d"),uMsg,uParam1,uParam2 );
switch(uMsg)
{
case SSIM_POST_CLOSE_SESSION://按会话ID关闭会话(Param1=会话ID,Param2=会话连续在线时间(用于防沉迷中统计在线时间))
{
pSession = GetSessionPtr((unsigned int)uParam1, &nIndex,uParam2);
if ( pSession )
{
CloseSessionAtListIndex( nIndex );
TRACE(_T("当前会话数量:%d"), m_SessionList.count());
}
else
{
OutputMsg(rmError,_T("关闭连接的时候找不到session%d"), uParam1);
}
}
break;
case SSIM_CHANGE_SESSION_STATE://网关向SessionServer投递改变会话状态的消息(Param1=会话ID,Param2=会话状态)
{
pSession = GetSessionPtr( (unsigned int)uParam1 );
if ( pSession && pSession->nState != uParam2 )
{
pSession->nState = (GSSTATE)uParam2;
//如果会话状态被改变为等待选择角色或等待进入游戏,则为会话标记超时时间
if ( pSession->nState == gsWaitQueryChar )
pSession->dwTimeOut = _getTickCount() + m_pSSManager->getSessionQueryCharTimeOut();
else if ( pSession->nState == gsWaitEntryGame )
pSession->dwTimeOut = _getTickCount() + m_pSSManager->getSessionEntryGameTimeOut();
else pSession->dwTimeOut = 0;
//广播改变会话状态
BroadCastUpdateSessionState(pSession);
}
}
break;
case SSIM_GATE_USER_CLOSED://网关向SessionServer投递网关用户已关闭的消息(Param1=会话ID)
//在会话服务器中不对此消息进行处理
break;
case SSIM_POST_ALL_CLIENT_MSG://向所有会话服务器的客户端发送消息(Param1=服务器类型,Param2=数据包,Param3=数据包大小)
{
SendAllClientMsg((SERVERTYPE)uParam1, (LPCSTR)uParam2, uParam3);
m_Allocator.FreeBuffer((LPVOID)uParam2);
}
break;
case SSIM_CONFIM_SESSION_ONLINE://确认会话是否在线(Param1=会话ID,Param2=服务器ID)
{
pSession = GetSessionPtr( (const unsigned int)uParam1 );
if ( pSession )
{
pSession->nConfimSrvCount = (int)(GetDBClientCount() + GetLogicClientCount(uParam2));
pSession->dwTimeOut = _getTickCount() + 10 * 1000;
OutputMsg(rmTip,_T("nConfimSrvCount=%d+%d=%d,serverindex=%d"),
GetDBClientCount(),GetLogicClientCount(uParam2),pSession->nConfimSrvCount,pSession->nServerIndex);
if ( pSession->nConfimSrvCount > 0 )
BroadCastSessionConfim(uParam1, pSession->nServerIndex);
//else m_pSSManager->PostGateUserConfimSessionResult((int)uParam1, FALSE);
}
else
{
OutputMsg(rmError,_T("SSIM_CONFIM_SESSION_ONLINE 找不到session =%d"),uParam1);
}
}
break;
case SSIM_CONFIM_SESSION_RESULT://数据或引擎客户端返回会话是否在线(Param1=会话ID,Param2=是否在线0:1)
{
pSession = GetSessionPtr( (const unsigned int)uParam1 );
if ( pSession && pSession->nConfimSrvCount )
{
pSession->nConfimSrvCount--;//减少需要等待回应的服务器数量
//如果会话已经在线,则返回网关用户的认证结果
if ( uParam2 )
{
//有一个服务器回应会话在线,则不用等待其他服务器返回了。
pSession->nConfimSrvCount = 0;
//m_pSSManager->PostGateUserConfimSessionResult((int)uParam1, TRUE);
}
//如果服务器回应会话未在线且等待回应的服务器数量已为0则表示会话没有在线了
else if ( pSession->nConfimSrvCount <= 0 )
{
//m_pSSManager->PostGateUserConfimSessionResult((int)uParam1, FALSE);
}
}
else
{
OutputMsg(rmError,_T("SSIM_CONFIM_SESSION_RESULT 找不到session =%d"),uParam1);
}
}
break;
case SSIM_CLOSE_SESSION_BY_ACCOUNT://通过账号字符串查找并关闭会话(Param1=字符串指针)
{
pSession = GetSessionPtrByAccount( (LPCSTR)uParam1, &nIndex );
if ( pSession )
{
CloseSessionAtListIndex(nIndex);
m_Allocator.FreeBuffer((LPVOID)uParam1);
}
}
break;
case SSIM_CLOSE_SESSION_BY_ACCOUNTID:
{
pSession = GetSessionPtr((const unsigned int)uParam1,&nIndex,uParam2 );
if ( pSession )
{
CloseSessionAtListIndex(nIndex);
}
}
break;
case SSIM_DEBUG_PRINT_SESSIONS://调试消息:打印全局会话(Param1=会话数量)
{
for (INT_PTR i=0; i<(INT_PTR)uParam1; ++i )
{
if ( i >= m_SessionList.count() )
break;
OutputMsg( rmWaning, _T("%s:%d->%d"), m_SessionList[i]->sAccount, m_SessionList[i]->nSessionID, m_SessionList[i]->nServerIndex );
}
}
break;
//踢掉在线的跨服用户
case SSIM_KICK_ONLINE_CROSSSERVER_ACTOR:
{
ProcessKickCrossActor((const unsigned int)uParam1,(const int)uParam2);
break;
}
default:
break;
}
}
void CSessionServer::ProcessKickCrossActor(const unsigned int nSessionId, const int nServerIndex)
{
char sBuffer[64];
PDATAHEADER pheader;
CDataPacket data(sBuffer,sizeof(sBuffer));
data.setLength(sizeof(*pheader));
data.setPosition(sizeof(*pheader));
data << (WORD)SessionServerProto::sKickCrossServerUser ;
data << (unsigned int)nSessionId;
pheader = (PDATAHEADER)data.getMemoryPtr();
pheader->tag=DEFAULT_TAG_VALUE ;
pheader->len = data.getLength() - sizeof(*pheader) ;
OutputMsg(rmNormal,"send Kick cross server actor,accountid=%d,serverindex=%d",(int)nSessionId,(int)nServerIndex);
SendLogicClientMsg(nServerIndex,data.getMemoryPtr(), data.getLength());
}
VOID CSessionServer::SingleRun()
{
TICKCOUNT dwCurTick = _getTickCount();
//提交新开启的会话数据
if ( m_SessionList.appendCount() > 0 )
{
m_SessionList.flush();
TRACE(_T("当前会话数量:%d"), m_SessionList.count());
}
//连接数据库
ConnectSQL();
//记录各个服务器的在线人数
if ( dwCurTick >= m_dwCheckOnlineLogTick )
{
SYSTEMTIME SysTime;
GetLocalTime(&SysTime);
if ( (SysTime.wMinute % 2) == 0 )//每1分钟记录一次在线
{
if ( !m_boOnlineLoged )
{
SendLogOnlineCount();
m_boOnlineLoged = TRUE;
}
}
else
{
m_boOnlineLoged = FALSE;
}
if ( (SysTime.wMinute % 60) == 5 )//每1分钟发IP的登陆情况过去
{
if ( !m_boIpLoged )
{
//SendOnlineIpStatus();
m_boIpLoged = TRUE;
}
}
else
{
m_boIpLoged = FALSE;
}
m_dwCheckOnlineLogTick = dwCurTick + 30 * 1000;
}
//1小时存盘1次
if(dwCurTick >= m_dwSaveRankTick)
{
if(m_SQLConnection.Connected())
{
SaveRankMsg();
}
m_dwSaveRankTick = dwCurTick +SAVE_RANK_INTERVAL;
}
//调用父类例行执行
Inherited::SingleRun();
// 更新AMC
m_pSSManager->UpdateAMC();
m_pSSManager->UpdateTask();
}
BOOL CSessionServer::ConnectSQL()
{
if ( !m_SQLConnection.Connected() )
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pSSManager->SetupSQLConnection(&m_SQLConnection);
if ( m_SQLConnection.Connect() )
{
mysql_options(m_SQLConnection.GetMySql(), MYSQL_SET_CHARSET_NAME, "utf8");
//设置下utf8
if(m_pSSManager->IsUtf8() )
{
mysql_set_character_set(m_SQLConnection.GetMySql(),"utf8");
}
InitACCountId();
InitRankMsg();
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
return TRUE;
}
bool CSessionServer::InitRankMsg()
{
int nError = m_SQLConnection.RealQuery(szLoadCsRank,strlen(szLoadCsRank));
if ( !nError )
{
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
int nCount = m_SQLConnection.GetRowCount();
while (pRow)
{
CRankItem rankItem;
rankItem.nActorid = strtoul(pRow[0],0,10);
sprintf(rankItem.sCharName, "%s", pRow[1]);
rankItem.sCharName[sizeof(rankItem.sCharName)-1] = 0;
rankItem.nProp1= StrToInt(pRow[2]); //sex
rankItem.nProp2 = StrToInt(pRow[3]); //vocation
rankItem.nKey = rankItem.nProp2;
rankItem.nServerId = StrToInt(pRow[4]);
rankItem.nValue =StrToInt(pRow[5]);
pRow = m_SQLConnection.NextRow();
PostRankMsg(rankItem);
}
m_SQLConnection.ResetQuery();
}
else
{
return false;
}
return true;
}
bool CSessionServer::SaveRankMsg()
{
INT_PTR nError = m_SQLConnection.Exec(szDeleteCSRank, 0);
if(nError)
{
return false;
}
m_SQLConnection.ResetQuery(); //函数调用里没有重置数据的
wylib::container::CBaseList<CRankItem> itemList ;
m_rankMgr.GetRankList(-1,itemList);
INT_PTR nRankCount = itemList.count();
char hugebuff[2048];
if(nRankCount > 0 ) //如果有数据
{
sprintf(hugebuff,szSaveCsRank); //表头放这里
char buff[1024] = {0};
for(INT_PTR i = 0; i < nRankCount; i++)
{
CRankItem *pItem = &itemList[i];
sprintf(buff,
"(%u, \"%s\", %d, %d, %d, %d)",
pItem->nActorid,
pItem->sCharName,
pItem->nProp1,
pItem->nProp2,
pItem->nServerId,
pItem->nValue);
strcat(hugebuff,buff);
if (i < nRankCount - 1)
{
strcat(hugebuff,",");
}
}
nError = m_SQLConnection.Exec(hugebuff);
if (!nError)
{
m_SQLConnection.ResetQuery();
}
}
OutputMsg(rmTip, _T("save csrank data to db"));
return true;
}
//初始化账户
bool CSessionServer::InitACCountId()
{
//查找最大的玩家的账户ID
char buff[128];
strcpy(buff,"select max(userid) from globaluser");
if ( m_SQLConnection.RealQuery(buff,strlen(buff)) )
{
OutputMsg(rmError, _T("can not call select max(userid) from globaluser"));
return false;
}
else
{
INT_PTR nSPguid= m_pSSManager->GetSPGUID(); //获取guid
OutputMsg(rmTip,"InitACCountId spid=%d",(int)nSPguid);
if(nSPguid ==0) return true; //为0的不需要处理
unsigned int nSpidMinActoridId = ((unsigned int)nSPguid << 24) ; //该运营商最小的accountid
OutputMsg(rmTip, _T("max spid account=%u"),nSpidMinActoridId);
bool bNeedInsert =false; //是否需要插入初始化记录
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
if ( pRow )
{
if ( pRow[0] )
{
unsigned int nMaxValue=(unsigned int) strtoul(pRow[0],0,10);
OutputMsg(rmTip, _T("db max account=%u"),nMaxValue);
if(nMaxValue < nSpidMinActoridId)
{
bNeedInsert =true;
}
}
else
{
OutputMsg(rmTip, _T("1 the account db has no account data exist, will init the account"));
bNeedInsert =true;
}
}
else
{
OutputMsg(rmTip, _T("2 the account db has no account data exist, will init the account"));
bNeedInsert =true;
}
m_SQLConnection.ResetQuery();
if(bNeedInsert) //需要初始化db往里边插入空记录
{
char buff[256];
char name[32];
sprintf(name,"__init_account_%d",(int)nSPguid);
sprintf(buff,"insert into globaluser (userid,account,passwd) values (%u,\"%s\",\"000\")",nSpidMinActoridId,name);
if(m_SQLConnection.Exec(buff))
{
OutputMsg(rmError, _T("init account spid fail"));
return false;
}
else
{
m_SQLConnection.ResetQuery();
OutputMsg(rmTip, _T("init account spid succeed, account=%u"),nSpidMinActoridId);
}
}
else
{
OutputMsg(rmTip, _T("account has init"));
}
}
return true;
}
PGAMESESSION CSessionServer::GetSessionPtr(const unsigned int nSessionId,PINT_PTR lpIndex ,Uint64 lKey,int nServerIndex)
{
INT_PTR i;
PGAMESESSION *pSessionList;
bool bNeedCheckKey = (lKey == UINT64(-1));
pSessionList = m_SessionList;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( pSessionList[i]->nSessionID == nSessionId && ( bNeedCheckKey==true || lKey ==pSessionList[i]->lKey ) && (nServerIndex ==-1 || nServerIndex ==pSessionList[i]->nServerIndex ))
{
if (lpIndex) *lpIndex = i;
return pSessionList[i];
}
}
return NULL;
}
//返回1个ip登陆了多少个号
int CSessionServer::GetLoginAccountCount(LONGLONG lIp)
{
INT_PTR i;
PGAMESESSION *pSessionList;
int nCount =0;
pSessionList = m_SessionList;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( pSessionList[i]->nIPAddr == lIp && pSessionList[i]->nIsRawLogin)
{
nCount ++;
}
}
return nCount;
}
PGAMESESSION CSessionServer::GetSessionPtrByAccount(LPCSTR sAccount, PINT_PTR lpIndex)
{
INT_PTR i;
PGAMESESSION *pSessionList;
pSessionList = m_SessionList;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( _stricmp(pSessionList[i]->sAccount, sAccount) == 0 )
{
if (lpIndex) *lpIndex = i;
return pSessionList[i];
}
}
return NULL;
}
BOOL CSessionServer::CloseSessionAtListIndex(const INT_PTR nIndex)
{
unsigned int nSessionId;
PGAMESESSION pSession;
BOOL boResult = FALSE;
//OutputMsg(rmNormal,"Current Thread =%d",(int)GetCurrentThreadId());
if ( m_SessionList.count() > nIndex )
{
boResult = TRUE;
pSession = m_SessionList[nIndex];
nSessionId = (unsigned int)pSession->nSessionID;
//关闭会话
OutputMsg(rmTip,_T("close Session,ID=%u,account=%s,serverin=%d"),nSessionId,pSession->sAccount,(int)pSession->nServerIndex);
//发给自己的服务器,需要删除这个会话
BroadCastCloseSession(nSessionId,pSession->lKey,pSession->nServerIndex);
//将会话关闭的行为记录到日志服务器中
/*
char sLastLoginIPAddr[64];
_asncpytA(sLastLoginIPAddr, inet_ntoa(*((in_addr*)&pSession->nIPAddr)));
m_pSSManager->getLogClient()->SetServerIndex(pSession->nServerIndex); //设置服务器的index
m_pSSManager->getLogClient()->SendLoginLog(ltLogout ,(int)nSessionId,
pSession->sAccount,sLastLoginIPAddr ,"");
*/
//删除会话指针
m_SessionList.lock();
m_SessionList.remove(nIndex);
m_SessionList.unlock();
m_Allocator.FreeBuffer(pSession);
TICKCOUNT nCurrentTick = _timeGetTime();
int nOnlineSeconds = (int)((nCurrentTick - pSession->dwSessionTick)/1000); //得到秒数
//如果有在线时间,则将在线时间更新到数据库中
if ( nOnlineSeconds > 0 )
{
if ( m_SQLConnection.Connected() )
{
char buff[256];
sprintf(buff,szUpdateUsernlineTime,nSessionId,nOnlineSeconds);
if (0 == m_SQLConnection.RealExec(buff,strlen(buff) ))
{
m_SQLConnection.ResetQuery();
}
else
{
OutputMsg(rmWaning,_T("sql %serror"),buff);
}
}
else
{
OutputMsg(rmError, _T("在关闭会话是试图更新账号数据(%d,%d)但SQL未就绪"), nSessionId, nOnlineSeconds);
}
}
}
else
{
OutputMsg(rmWaning,_T("close nIndex =%d,fail"),nIndex);
}
return boResult;
}
INT_PTR CSessionServer::SendAllClientMsg(const SERVERTYPE eServerType, LPCSTR sMsg, const size_t dwSize)
{
INT_PTR i, nSendCount = 0;
CSessionClient *pClient;
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
if ( pClient && pClient->connected() && pClient->registed() )
{
if ( eServerType == InvalidServer || pClient->getClientType() == eServerType )
{
//OutputMsg(rmTip,_T("SendAllClientMsg send msg to client:serverindex=%d,clientName=%s"),
// pClient->getClientServerIndex(),pClient->getClientName());
pClient->AppendSendBuffer(sMsg, dwSize );
nSendCount++;
}
}
}
return nSendCount;
}
INT_PTR CSessionServer::SendLogicClientMsg(const INT_PTR nServerIndex, LPCSTR sMsg, const size_t dwSize)
{
INT_PTR i, nSendCount = 0;
CSessionClient *pClient;
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
if ( pClient && pClient->connected() && pClient->registed() && pClient->getClientType() == GameServer && pClient->getClientServerIndex() == (int)nServerIndex)
{
pClient->AppendSendBuffer(sMsg, dwSize );
//OutputMsg(rmTip,"Send LogicMsg, serverindex=%d,size=%d",(int)nServerIndex,(int)dwSize);
nSendCount++;
}
}
return nSendCount;
}
INT_PTR CSessionServer::SendGroupLogicClientMsg(const int nCommServerId, LPVOID data, const SIZE_T nSize)
{
INT_PTR i, nSendCount = 0;
CSessionClient *pClient;
for (i = m_ClientList.count() - 1; i > -1; --i)
{
pClient = (CSessionClient*)m_ClientList[i];
if ( pClient && pClient->registed()
&& GameServer == pClient->getClientType()
&& nCommServerId == pClient->GetCommonServerId())
{
pClient->AppendSendBuffer(data, nSize);
nSendCount++;
}
}
return nSendCount;
}
INT_PTR CSessionServer::SendAllDBAndIndexEngineMsg(const INT_PTR nServerIndex, LPCSTR sMsg, const size_t dwSize)
{
INT_PTR i, nSendCount = 0;
CSessionClient *pClient;
m_ClientList.lock();
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
////debug
//if (pClient)
//{
// OutputMsg(rmTip,_T("SendAllDBAndIndexEngineMsg pclient:connected=%d,registed=%d,clienttype=%d,serverindex=%d,clientName=%s"),
// (int)(pClient->connected()),(int)(pClient->registed()),pClient->getClientType(),
// pClient->getClientServerIndex(),pClient->getClientName());
//}
////end debug
if ( !pClient || !pClient->connected() || !pClient->registed() )
continue;
if ( pClient->getClientType() == DBServer ||
(pClient->getClientType() == GameServer && pClient->getClientServerIndex() == nServerIndex) )
{
pClient->AppendSendBuffer(sMsg, dwSize );
nSendCount++;
//OutputMsg(rmTip,_T("SendAllDBAndIndexEngineMsg send msg to client:serverindex=%d,clientName=%s"),
// pClient->getClientServerIndex(),pClient->getClientName());
}
}
m_ClientList.unlock();
return nSendCount;
}
INT_PTR CSessionServer::BroadCastUpdateSessionState(PGAMESESSION pSession)
{
char sBuffer[32];
PDATAHEADER pheader;
CDataPacket data(sBuffer,sizeof(sBuffer));
data.setLength(sizeof(*pheader));
data.setPosition(sizeof(*pheader));
data << (WORD)SessionServerProto::sUpdateSession ;
data << (int)pSession->nSessionID;
data << (int)pSession->nState;
pheader = (PDATAHEADER)data.getMemoryPtr();
pheader->tag=DEFAULT_TAG_VALUE ;
pheader->len = data.getLength() - sizeof(*pheader) ;
//向所有数据服务器发送会话状态变更消息
INT_PTR nResult = SendAllClientMsg(DBServer,data.getMemoryPtr(), data.getLength());
//如果会话登录到某个逻辑服务器,则向此逻辑服务器发送会话状态变更消息
if ( pSession->nServerIndex > 0 )
{
nResult += SendLogicClientMsg(pSession->nServerIndex,data.getMemoryPtr(), data.getLength());
}
return nResult;
}
INT_PTR CSessionServer::BroadCastCloseSession(const UINT64 nSessionId,Uint64 lKey,const int nServerIndex)
{
char sBuffer[64];
PDATAHEADER pheader;
CDataPacket data(sBuffer,sizeof(sBuffer));
data.setLength(sizeof(*pheader));
//关闭号
data.setPosition(sizeof(*pheader));
data << (WORD)SessionServerProto::sCloseSession ;
data <<(unsigned int) nSessionId;
data <<(Uint64) lKey;
pheader = (PDATAHEADER)data.getMemoryPtr();
pheader->tag=DEFAULT_TAG_VALUE ;
pheader->len = data.getLength() - sizeof(*pheader) ;
//向所有数据服务器、引擎服务器发送删除会话消息
if(nServerIndex >0 )
{
return SendLogicClientMsg(nServerIndex, data.getMemoryPtr(), data.getLength()) ;
}
else
{
return SendAllClientMsg(LogServer, data.getMemoryPtr(), data.getLength() );
}
//return SendAllClientMsg(InvalidServer, data.getMemoryPtr(), data.getLength());
}
INT_PTR CSessionServer::BroadCastSessionConfim(const UINT64 nSessionId, const INT_PTR nServerIndex)
{
INT_PTR nResult =0;
char sBuffer[32];
PDATAHEADER pheader;
CDataPacket data(sBuffer,sizeof(sBuffer));
data.setLength(sizeof(*pheader));
data.setPosition(sizeof(*pheader));
data << (WORD)SessionServerProto::sQuerySessionExist ;
data << (unsigned int)nSessionId;
pheader = (PDATAHEADER)data.getMemoryPtr();
pheader->tag=DEFAULT_TAG_VALUE ;
pheader->len = data.getLength() - sizeof(*pheader) ;
//如果nServerIndex为0则向所有数据服务器、引擎服务器发送确认会话是否在线的消息
if ( !nServerIndex )
{
nResult = SendAllClientMsg(InvalidServer, data.getMemoryPtr(), data.getLength());
}
else
{
nResult = SendAllDBAndIndexEngineMsg(nServerIndex, data.getMemoryPtr(), data.getLength());
}
return nResult;
}
//踢掉在线的用户
VOID CSessionServer::PostKickCrossActor(const INT_PTR nSessionId, const int nServerIndex)
{
PostInternalMessage(SSIM_KICK_ONLINE_CROSSSERVER_ACTOR, nSessionId,nServerIndex,0);
}
VOID CSessionServer::PostAllClientMsg(const SERVERTYPE eServerType, LPCSTR sMsg)
{
size_t dwSize = strlen(sMsg);
LPVOID lpData = m_Allocator.AllocBuffer(dwSize);
memcpy(lpData, sMsg, dwSize);
PostInternalMessage(SSIM_POST_ALL_CLIENT_MSG, eServerType, (UINT_PTR)lpData, dwSize);
}
BOOL CSessionServer::GetSession(const INT_PTR nSessionId, OUT PGAMESESSION pSession,int nServerIndex)
{
BOOL boResult = FALSE;
CSafeLock sl(&m_SessionListLock);
PGAMESESSION pSessionPtr = GetSessionPtr((unsigned int)nSessionId, NULL,Uint64(-1),nServerIndex);
if ( pSessionPtr )
{
*pSession = *pSessionPtr;
boResult = TRUE;
}
return boResult;
}
PGAMESESSION CSessionServer::GetSpecialServerSession(const INT_PTR nSessionId, const int nServerIndex)
{
INT_PTR i;
PGAMESESSION *pSessionList= m_SessionList;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( pSessionList[i]->nSessionID == nSessionId && pSessionList[i]->nServerIndex == nServerIndex)
{
return pSessionList[i];
}
}
return NULL;
}
//logic server count
INT_PTR CSessionServer::GetLogicClientCount(const INT_PTR nServerIndex)
{
OutputMsg(rmTip,_T("GetLogicClientCount:%d"),nServerIndex);
if ( !nServerIndex )
return m_nEngineClientCount;
INT_PTR i, nResult = 0;
CSessionClient *pClient;
m_ClientList.lock();
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
////debug
//if (pClient)
//{
// OutputMsg(rmTip,_T("GetLogicClientCount pClient:connected=%d,registed=%d,clienttype=%d,serverindex=%d,clientName=%s"),
// (int)(pClient->connected()),(int)(pClient->registed()),pClient->getClientType(),
// pClient->getClientServerIndex(),pClient->getClientName());
//}
////end debug
if ( pClient && pClient->connected() && pClient->registed()
&& pClient->getClientType() == GameServer && pClient->getClientServerIndex() == nServerIndex )
{
nResult ++;
//OutputMsg(rmTip,_T("--------------------------%d"),pClient->getClientServerIndex());
////debug
//if (pClient)
//{
// OutputMsg(rmTip,_T("GetLogicClientCount pClient2:connected=%d,registed=%d,clienttype=%d,serverindex=%d,clientName=%s"),
// (int)(pClient->connected()),(int)(pClient->registed()),pClient->getClientType(),
// pClient->getClientServerIndex(),pClient->getClientName());
//}
////end debug
}
}
m_ClientList.unlock();
return nResult;
}
INT_PTR CSessionServer::UserCanLoginToServer(const INT_PTR nServerIndex)
{
INT_PTR i, nResult = -1;
CSessionClient *pClient;
m_ClientList.lock();
for ( i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
if ( pClient && pClient->connected() && pClient->registed()
&& pClient->getClientType() == GameServer && pClient->getClientServerIndex() == nServerIndex )
{
//判断服务器人员是否已满,
if ( pClient->m_nUserCount < pClient->m_nUserLimit )
nResult = 0;
else nResult = -1;
break;
}
}
m_ClientList.unlock();
return nResult;
}
//此函数是被网关线程调用的
BOOL CSessionServer::PostOpenSession(const INT_PTR nServerIndex,
const INT_PTR nRawServerIndex,
LPCSTR sAccount,
const unsigned int nSessionId,
const INT_PTR nIPAddr,
const INT_PTR dwTodayOnlineSec,
INT_PTR nGmLevel,
UINT64 lKey ,
INT_PTR nGateIndex,
bool bIsWhiteLogin,
bool bCommonMsg
)
{
char sBuffer[256];
PGAMESESSION pSession;
BOOL boNewSession = FALSE;
m_SessionList.lock();
pSession = GetSessionPtr(nSessionId);
m_SessionList.unlock();
if ( !pSession )
//每次都去new一个
{
pSession = (PGAMESESSION)m_Allocator.AllocBuffer(sizeof(*pSession));
boNewSession = TRUE;
}
ZeroMemory(pSession, sizeof(*pSession));
pSession->nSessionID = nSessionId;
pSession->nServerIndex = (int)nServerIndex;
if(nServerIndex == nRawServerIndex)
{
pSession->nIsRawLogin =1 ; //原来的服务器ID
}
else
{
pSession->nIsRawLogin =0;
}
pSession->nIPAddr = nIPAddr;
pSession->lKey = lKey; //登陆的key值
//会话建立的时候就标记为等待查询角色状态,这个时候将连接数据服务器
pSession->nState = gsWaitQueryChar;
pSession->dwSessionTick = _timeGetTime();
pSession->dwTimeOut = pSession->dwSessionTick + m_pSSManager->getSessionQueryCharTimeOut();
pSession->nGmLevel= (int)nGmLevel;
_asncpytA(pSession->sAccount, sAccount);
//追加会话数据
if ( boNewSession )
{
m_SessionList.append(pSession);
}
//向日志服务器记录登录日志格式为USERID/ACCOUNT/GAMETYPE/IPADDR/CHARNAME
/*
m_pSSManager->getLogClient()->SetServerIndex(nServerIndex);
char sLoginIPAddr[64];
_asncpytA(sLoginIPAddr, inet_ntoa(*((in_addr*)&nIPAddr)));
m_pSSManager->getLogClient()->SendLoginLog(ltLogin ,(int)nSessionId,
pSession->sAccount,sLoginIPAddr ,"");
*/
//广播消息
GLOBALSESSIONOPENDATA SessionData ;
SessionData.nSessionId = (INT)nSessionId;
SessionData.nServerIndex = (INT)nServerIndex; //?
SessionData.nRawServerId = (INT)nRawServerIndex;
SessionData.nClientIPAddr = (LONGLONG)nIPAddr;
SessionData.dwFCMOnlineSec = (DWORD)dwTodayOnlineSec;
SessionData.nGmLevel =(int) nGmLevel; //GM等级
SessionData.lKey =lKey;
SessionData.nGateIndex = (int)nGateIndex; //在服务器的index
SessionData.eState =(GSSTATE) (bIsWhiteLogin?0:1);
_asncpytA(SessionData.sAccount, sAccount);
PDATAHEADER pheader;
CDataPacket data(sBuffer,sizeof(sBuffer));
data.setLength(sizeof(*pheader));
data.setPosition(sizeof(*pheader));
data << (WORD)SessionServerProto::sOpenSession ; //cmd
data << SessionData; //数据
pheader = (PDATAHEADER)data.getMemoryPtr();
pheader->tag=DEFAULT_TAG_VALUE ;
pheader->len = data.getLength() - sizeof(*pheader) ;
if(bCommonMsg == false)
{
//只向特定的逻辑服发送
SendLogicClientMsg(nServerIndex, data.getMemoryPtr(), data.getLength());
}
else
{
//发送给会话中心服
m_pSSManager->getSessionCenter()->SendSSCommonMsg((const int)nServerIndex, data.getMemoryPtr(), data.getLength());
}
return TRUE;
}
VOID CSessionServer::PostCloseSessionByAccountId(Uint64 nAccountId,UINT64 lKey)
{
PostInternalMessage(SSIM_CLOSE_SESSION_BY_ACCOUNTID, nAccountId, lKey,0,0);
}
VOID CSessionServer::PostCloseSessionByAccount(const LPCSTR sAccount)
{
LPSTR sAccountStr = (LPSTR)m_Allocator.AllocBuffer(sizeof(sAccountStr[0]) * (strlen(sAccount) + 1));
strcpy(sAccountStr, sAccount);
PostInternalMessage(SSIM_CLOSE_SESSION_BY_ACCOUNT, (UINT_PTR)sAccountStr, 0, 0);
}
VOID CSessionServer::EnumConnections(EnumConnectionFn lpFn, LPCVOID lpParam)
{
CSessionClient *pClient;
UINT uRetCode;
m_ClientList.lock();
for ( INT_PTR i=m_ClientList.count() - 1; i>-1; --i )
{
pClient = (CSessionClient*)m_ClientList[i];
if ( pClient && pClient->connected())
{
uRetCode = lpFn(lpParam, pClient);
if ( uRetCode )
break;
}
}
m_ClientList.unlock();
}
void CSessionServer::PostAMCTaskMsg(CAMClient::tagTASKMsg &data)
{
CSessionClient *pClient = 0;
//unsigned int nActorid =(unsigned int) data.lOPPtr; //角色id
int nServerId = data.nServerId; //服务器的id
OutputMsg(rmTip,"[SessionServer->SessionClient]PostAMCTaskMsg op=%d,serverindex=%d,accountid=%u",
data.nCmd,data.nServerId,data.nUserId);
for (INT_PTR i= m_ClientList.count() - 1; i > -1; --i)
{
pClient = (CSessionClient*)m_ClientList[i];
if (pClient && pClient->connected() && pClient->getClientType() == GameServer)
{
if(pClient->GetServerId() == nServerId)
{
pClient->SendAmTaskAck(data);
return;
}
}
}
}
void CSessionServer::PostAMCMsg(const CAMClient::AMOPData &data)
{
CSessionClient *pClient = 0;
//CSessionClient *client = (CSessionClient *)data.lOPPtr;
unsigned int nActorid =(unsigned int) data.lOPPtr; //角色id
int nServerId = data.nServerId; //服务器的id
OutputMsg(rmTip,"[SessionServer->SessionClient]PostAMCMsg op=%d,serverindex=%d,accountid=%u,actorid=%u",
data.opType,data.nServerId,data.nUserId,nActorid);
for (INT_PTR i= m_ClientList.count() - 1; i > -1; --i)
{
pClient = (CSessionClient*)m_ClientList[i];
if (pClient && pClient->connected() && pClient->getClientType() == GameServer)
{
if(pClient->GetServerId() == nServerId)
{
pClient->sendAMCMsgAck(data);
return;
}
/*
if(client == NULL ) //这个是用来返回充值的
{
//OutputMsg(rmError,"pClient=%d",(int)pClient->getClientServerIndex());
if(pClient->getClientServerIndex() == data.nServerId)
{
pClient->sendAMCMsgAck(data);
return;
}
}
else if(client == pClient )
{
pClient->sendAMCMsgAck(data);
return;
}
*/
}
}
OutputMsg(rmError,"[SessionServer->SessionClient]PostAMCMsg No client found,op=%d,serverindex=%d,userid=%u",data.opType,data.nServerId,data.nUserId);
}
/*
* Comments: 解封ip
* Parameter: long long lIp:
* @Return void:
*/
void CSessionServer::UnSealIp(char *sIp)
{
long long lIp = GetIntIp(sIp);
if(lIp ==0 )return;
CBaseList<unsigned long long>& blackips= m_pSSManager->GetBlackIpList(); //获取黑名单列表
INT_PTR nCount = blackips.count();
bool flag =false;
for(INT_PTR i=0; i< nCount ;i++)
{
if(blackips[i] == lIp)
{
blackips.remove(i);
OutputMsg(rmTip,"unSeal ip=%s",sIp); // 解封这个i
break;
}
}
}
void CSessionServer::SealIp(char *sIp)
{
long long lIp = GetIntIp(sIp);
if(lIp ==0 )return;
//OutputMsg(rmTip,"Seal ip=%s",sIp); // 解封这个ip
CBaseList<unsigned long long>& blackips= m_pSSManager->GetBlackIpList(); //获取黑名单列表
INT_PTR nCount = blackips.count();
bool flag =false;
INT_PTR i;
for( i=0; i< nCount ;i++)
{
if(blackips[i] == lIp)
{
flag =true;
break;
}
}
if(!flag)
{
OutputMsg(rmTip,"Seal ip=%s",sIp); // 解封这个ip
blackips.add(lIp);
}
else
{
return ;
}
PGAMESESSION *pSessionList =m_SessionList;
for ( i=m_SessionList.count() - 1; i>-1; --i )
{
if ( pSessionList[i]->nIPAddr == lIp )
{
OutputMsg(rmTip,"Seal ip=%s,kick account=%s,serverindex=%d",sIp, pSessionList[i]->sAccount, (int)pSessionList[i]->nServerIndex); // 解封这个ip
ProcessKickCrossActor((unsigned int)pSessionList[i]->nSessionID,pSessionList[i]->nServerIndex);
CloseSessionAtListIndex(i);
}
}
}
long long CSessionServer::GetIntIp(char *sIp)
{
INT_PTR nSize = strlen(sIp);
bool flag =true;
int nDoutCount =0;
for(INT_PTR i=0; i < nSize; i++)
{
//合法的输入
if(sIp[i] =='.')
{
nDoutCount ++;
//".不能出现在最前面"
if( i==0 || i== (nSize-1) )
{
flag =false;
break;
}
}
else if(sIp[i] >='0' &&sIp[i] <='9' )
{
continue;
}
else
{
flag =false;
break;
}
}
if(nDoutCount < 3)
{
flag =false;
}
if(!flag )
{
OutputMsg(rmWaning,"InValide ip=%s",sIp);
return 0;
}
else
{
return inet_addr (sIp); //计算这个ip
}
}
void CSessionServer::OnSendPlatformResultToClient(int nServerIndex,CDataPacketReader &inPacket)
{
CSessionClient *pClient = 0;
for (INT_PTR i= m_ClientList.count() - 1; i > -1; --i)
{
pClient = (CSessionClient*)m_ClientList[i];
if (pClient && pClient->connected() && pClient->getClientType() == GameServer)
{
if(pClient->GetServerId() == nServerIndex)
{
pClient->OnSendReqCommonPlatformResult(inPacket);
return;
}
}
}
}