#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 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& 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 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& 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& 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; } } } }