#include "StdAfx.h" #include "DataProcess.h" #include "SockProcess.h" HANDLE g_hStdOut; unsigned int CRunDataProcesser::s_nSndThreadSleepTime = 20; extern bool g_ServerIsRunning; //接收数据的线程 #ifdef _MSC_VER VOID STDCALL CRunDataProcesser::RecvDataProcdaessRoutine(void *arg) #else VOID* CRunDataProcesser::RecvDataProcessRoutine(void *arg) #endif { CRunDataProcesser * pRunData = (CRunDataProcesser *)arg; //LPCRITICAL_SECTION pQueueLock; CBaseList *pRecvList; PCLIENTRECVBUF *ppRecvBufs, pRecvBuf; PRUNGATEUSERSESSION pSession; INT_PTR nBufferCount; TICKCOUNT dwProcStartTick, dwLockDataTick, dwLockCheckTick, dwSendCheckTick, dwPerfDumpTick, dwSendGateUserInfo; //pQueueLock = &pRunData->m_RecvQueueLock; pRecvList = pRunData->m_pRecvProcList; pRunData->m_llSendKeepAliveTime = 0; dwLockDataTick = dwLockCheckTick = dwPerfDumpTick = dwSendGateUserInfo = _getTickCount(); dwSendCheckTick = dwSendGateUserInfo + 2000; while ( !pRunData->m_boStoping ) { dwProcStartTick = _getTickCount(); //发送网关自检 if ( dwProcStartTick - dwSendCheckTick >= 2000 ) { pRunData->SendCheck( GM_CHECKSERVER ); dwSendCheckTick = dwProcStartTick; pRunData->m_llSendKeepAliveTime = dwSendCheckTick; } // 发送网关用户数目,一分钟发一次 if (dwProcStartTick - dwSendGateUserInfo >= 60000 ) { pRunData->SendGateUserInfo(); dwSendGateUserInfo = dwProcStartTick; } //检查会话关闭 if ( dwProcStartTick - dwLockCheckTick >= 5000 ) { if ( pRunData->CheckCloseSessions( dwProcStartTick - dwLockCheckTick >= 10000 ) ) { dwProcStartTick = dwLockCheckTick = _getTickCount(); } } // dump statistic if (dwProcStartTick - dwPerfDumpTick >= 120000) { CTimeProfMgr::getSingleton().dump(); dwPerfDumpTick = dwProcStartTick; } //如果未能获得数据队列锁则让出本次CPU时间 if ( !TryEnterCriticalSection( &pRunData->m_RecvQueueLock ) ) { if ( dwProcStartTick - dwLockDataTick < 60 ) { Sleep( 1 ); continue; } else { EnterCriticalSection( &pRunData->m_RecvQueueLock ); dwProcStartTick = dwLockDataTick = _getTickCount(); } } else dwLockDataTick = dwProcStartTick; //交换数据处理队列 pRecvList = pRunData->m_pRecvAppendList; pRunData->m_pRecvAppendList = pRunData->m_pRecvProcList; pRunData->m_pRecvProcList = pRecvList; LeaveCriticalSection( &pRunData->m_RecvQueueLock ); //如果没有待处理的数据则让出本次CPU时间 nBufferCount = pRecvList->count(); if ( !nBufferCount ) { Sleep( 1 ); continue; } ppRecvBufs = (PCLIENTRECVBUF*)(void**)(*pRecvList); while ( nBufferCount > 0 ) { pRecvBuf = *ppRecvBufs; nBufferCount--; ppRecvBufs++; pSession = pRecvBuf->pSession; if ( pRecvBuf->nBufferSize > 0 ) { //如果会话被关闭或效验过期则不予处理 if ( pSession->nSocket != INVALID_SOCKET && pSession->nVerifyIdx == pRecvBuf->nVerify && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { pSession->dwClientMsgTick = dwProcStartTick; //OutputMsg( rmTip, "dwProcStartTick=%I64d",dwProcStartTick); pRunData->ProcessUserRecvPacket( pSession, (char*)(pRecvBuf + 1), pRecvBuf->nBufferSize ); pSession->nRecvPacketCount++; } } free( pRecvBuf ); } pRecvList->clear(); pRunData->m_dwLastProcUsrMsgTime = _getTickCount() - dwProcStartTick; //循环小于指定时间则休眠一次 //if ( pRunData->m_dwLastProcUsrMsgTime < 16 ) if(TRUE) { Sleep ( 1 ); } } ExitThread( 0 ); } //发送数据的线程 #ifdef _MSC_VER VOID STDCALL CRunDataProcesser::SendDataProcessRoutine(void* arg) #else VOID* CRunDataProcesser::SendDataProcessRoutine(void* arg) #endif { PRUNDATASENDTHREAD pRunThread = (PRUNDATASENDTHREAD)arg; TICKCOUNT dwProcStartTick; CRunDataProcesser *pRunData; int nLockSendBufQLockFail = 0; pRunData = pRunThread->pRunData; while ( !pRunData->m_boStoping ) { dwProcStartTick = _getTickCount(); if ( pRunData->CopyWaitSendBuffers( pRunThread, TRUE) ) nLockSendBufQLockFail = 0; else nLockSendBufQLockFail ++; pRunData->CheckSendSessionBuffers( pRunThread ); //循环小于指定时间则休眠一次 pRunThread->dwProcTick = _getTickCount() - dwProcStartTick; //if ( pRunThread->dwProcTick < 20 ) { dwProcStartTick = _getTickCount(); Sleep(s_nSndThreadSleepTime); TICKCOUNT curTick = _getTickCount(); pRunThread->dwSleepTick = curTick - dwProcStartTick; } /*else pRunThread->dwSleepTick = 0;*/ } ExitThread( 0 ); } //收到了服务器的数据,进行处理 //VOID CRunDataProcesser::ProcessRecvBuffers(const GateMsg* msg) VOID CRunDataProcesser::ProcessRecvBuffers(const GATEMSGHDR* pHeader, LPCSTR pData, size_t nLen) { Assert(pHeader->dwGateCode == RUNGATECODE); /*if (msg->header.wIdent == GM_DATA) Assert(msg->header.wTemp == RUNTEMPCODE);*/ if (s_nIgnoreDataPacket) return; //如果是关闭服务器的话 if(pHeader->wIdent ==GM_CLOSE_SERVER) { OutputMsg(rmTip,"Back server close from back"); g_ServerIsRunning = false; return; } else if (pHeader->wIdent == GM_APPBIGPACK) { char* pBuffEnd = (char *)pData + nLen; GATEMSGHDR* pCurHeader = (GATEMSGHDR *)pData; while ((char*)pCurHeader < pBuffEnd) { if (pCurHeader->dwGateCode != RUNGATECODE) { OutputMsg(rmError, _T("%s recv packet invalid..."), __FUNCTION__); break; } DispathRecvMessage(pCurHeader, (const char*)(pCurHeader+1), pCurHeader->nDataSize); pCurHeader = (GATEMSGHDR *)((char *)pCurHeader + (sizeof(GATEMSGHDR) + pCurHeader->nDataSize)); } } else DispathRecvMessage((GATEMSGHDR * const)pHeader, pData, nLen); } VOID CRunDataProcesser::DispathRecvMessage(const PGATEMSGHDR pMsgHdr, const char *pBuffer, SIZE_T nBufSize) { PRUNGATEUSERSESSION pSession; /* if(GM_DATA ==pMsgHdr->wIdent) { OutputMsg(rmTip, _T("收到后台数据,cmd=%d,wSessionIdx=%d,wServerIdx=%d,socket=%d\n"), pMsgHdr->wIdent, pMsgHdr->wSessionIdx,pMsgHdr->wServerIdx,pMsgHdr->nSocket); } */ switch ( pMsgHdr->wIdent ) { case GM_CLOSE: if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount ) { pSession = &m_Sessions[pMsgHdr->wSessionIdx]; if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { SendCloseSession( pSession, FALSE, enReasonGM ); } else { OutputMsg( rmWaning, _T("GM_CLOSE socket不匹配 wSessionIdx=%d,本地Socket=%d,后台的为%d"), pMsgHdr->wSessionIdx, pSession->nSocket, pMsgHdr->nSocket ); } } break; case GM_CHECKCLIENT: { // 保存服务器的时间 if (m_llSendKeepAliveTime > 0) { if (m_nCheckTimeCount < 10) { TICKCOUNT nTimeDiff = pMsgHdr->tickCount - _getTickCount(); m_llOccuTimeDiff += nTimeDiff; m_nCheckTimeCount++; m_llSvrTimeDiff = (long long)(m_llOccuTimeDiff / (float)m_nCheckTimeCount); OutputMsg(rmNormal, _T("timediff=%lld,result dif=%lld,checkTimecount=%d"), nTimeDiff, m_llSvrTimeDiff, m_nCheckTimeCount); } } /*OutputMsg(rmNormal, _T("------logicSvrTime=%I64d gateTime=%I64d, timeDif=%I64d"), pMsgHdr->tickCount, nCurrTick, m_llSvrTimeDiff);*/ } break; case GM_APPKEEPALIVE: { // 给服务器会应答消息 pSession = &m_Sessions[pMsgHdr->wSessionIdx]; if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { SendKeepAliveAck( pSession, pBuffer, nBufSize); } break; } case GM_SERVERUSERINDEX: if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount ) { pSession = &m_Sessions[pMsgHdr->wSessionIdx]; if ( pSession->nSocket == pMsgHdr->nSocket && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { pSession->nServerIdx = pMsgHdr->wServerIdx; OutputMsg(rmNormal, _T("recv GM_ServerIndex msg. socket=%d, sessionId=%d, set serverIdx=%d"), (int)pSession->nSocket, (int)pSession->nIndex, pSession->nServerIdx); } else { OutputMsg(rmError, _T("GM_ServerIndex Error, session closed or socket unmatch(session socket=%d, sessionId=%d, msghdr socket=%d"), (int)pSession->nSocket, (int)pSession->nIndex, (int)pMsgHdr->nSocket); } } break; case GM_DATA: if ( pMsgHdr->wSessionIdx < m_nMaxSessionCount ) { pSession = &m_Sessions[pMsgHdr->wSessionIdx]; if ( !pSession->boMarkToClose && !pSession->boRemoteClosed ) { if ( pSession->nSocket == pMsgHdr->nSocket ) { PostUserServerData( pSession, pBuffer, (INT)nBufSize, TRUE, TRUE, (TICKCOUNT)pMsgHdr->tickCount); } else { OutputMsg( rmWaning, "GM_DATA 会话(%d:%s)套接字不匹配,data Socket=%d,local socket=%d", pMsgHdr->wSessionIdx, pSession->sLoginCharName, pMsgHdr->nSocket,pSession->nSocket ); //SendCloseSession((SOCKET)pMsgHdr->nSocket); //如果套接字不匹配 //SendCloseSession( pSession, TRUE, enReasonAllSessionClose ); } } else { OutputMsg( rmWaning, "GM_DATA 会话(%d:%s,%d,%d)已关闭", pMsgHdr->wSessionIdx, pSession->sLoginCharName, (int)(pSession->boMarkToClose),(int)(pSession->boRemoteClosed)); //这种情况下再次向逻辑发送关闭连接 //SendCloseSession((SOCKET)pMsgHdr->nSocket); } } else OutputMsg( rmWaning, "GM_DATA 会话ID无效(%d)", pMsgHdr->wSessionIdx ); break; default: { GotError( __FUNCTION__, _T("无效的消息序列"), pMsgHdr->wIdent ); } break; } } VOID CRunDataProcesser::OnConnected() { Inherited::OnConnected(); m_llSendKeepAliveTime = 0; m_nCheckTimeCount = 0; m_llOccuTimeDiff = 0; OutputMsg(rmTip, _T("BackServer Connected")); } VOID CRunDataProcesser::OnClosed() { Inherited::OnClosed(); CloseAllSessions(true); } VOID CRunDataProcesser::OnError(int errorCode) { OutputError(errorCode, _T("BackServer Socket Error ")); } VOID CRunDataProcesser::OnDisconnected() { m_llSvrTimeDiff = 0; m_nCheckTimeCount = 0; m_llOccuTimeDiff = 0; OutputMsg(rmWaning, _T("BackServer Connection Closed")); } CRunDataProcesser::CRunDataProcesser(const int nMaxSessionCount) :Inherited() { m_nActiveUser = 0; m_boStoping = FALSE; m_boStarted = FALSE; m_DataProcessType = dp_Default; /* m_hPipe = INVALID_HANDLE_VALUE; strcpy( m_sPipeName, "\\\\.\\pipe\\default" ); sprintf( m_sGateName, "游戏网关%d", _getTickCount() % 100 ); */ m_hProcRecvThread = NULL; ZeroMemory( m_SendThreads, sizeof(m_SendThreads) ); m_nSendThreadCount = 2; m_nMaxSessionCount = nMaxSessionCount; // 默认值: 16384 m_Sessions = NULL; m_pSockProcesser = NULL; InitializeCriticalSection( &m_SessionLock ); if ( m_Sessions ) ZeroMemory( m_Sessions, sizeof(m_Sessions) ); InitializeCriticalSection( &m_RecvQueueLock ); m_pRecvAppendList = &m_RecvQueue[0]; m_pRecvProcList = &m_RecvQueue[1]; m_ServerBuf.lpBuffer= NULL; m_ServerBuf.nSize = 0; m_ServerBuf.nOffset = 0; m_nUserVerify = 1; m_dwProcessRecvSize = 0; m_boPrintC2SMsg = FALSE; m_boPrintS2CMsg = FALSE; m_llSvrTimeDiff = 0; m_nCheckTimeCount = 0; m_llOccuTimeDiff = 0; InitSendThreadData(); //m_DataPacker.SetNeedEncrypt(true); //需要加密 } CRunDataProcesser::~CRunDataProcesser() { Stop(); UninitSendThreadData(); DeleteCriticalSection( &m_RecvQueueLock ); DeleteCriticalSection( &m_SessionLock ); } VOID CRunDataProcesser::InitSessions() { int i; PRUNGATEUSERSESSION pSession; EnterCriticalSection( &m_SessionLock ); if ( !m_Sessions ) { m_Sessions = (PRUNGATEUSERSESSION)malloc(sizeof(m_Sessions[0]) * m_nMaxSessionCount); ZeroMemory( m_Sessions, sizeof(m_Sessions[0]) * m_nMaxSessionCount ); } pSession = m_Sessions; for ( i=0; inIndex = i; pSession->nSocket = INVALID_SOCKET; #ifdef WIN32 pSession->Overlapped.pUser = pSession; #endif pSession->nServerIdx = 0; pSession->btPacketIdx = 0; pSession->wPacketError = 0; pSession->nRecvPacketCount = 0; pSession->nSendPacketCount = 0; pSession->boMarkToClose = false; pSession->boRemoteClosed = false; pSession->boSendAvaliable = true; INIT_SESSION_SEND( pSession ); pSession++; } LeaveCriticalSection( &m_SessionLock ); } VOID CRunDataProcesser::UninitSessions() { int i; PRUNGATEUSERSESSION pSession; if ( !m_Sessions ) return; EnterCriticalSection( &m_SessionLock ); pSession = m_Sessions; for ( i=0; iRecvBuf.lpBuffer ) { free( pSession->RecvBuf.lpBuffer ); pSession->RecvBuf.lpBuffer = NULL; pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0; } if ( pSession->SendBuf.lpBuffer ) { free( pSession->SendBuf.lpBuffer ); pSession->SendBuf.lpBuffer = NULL; pSession->SendBuf.nSize = pSession->SendBuf.nOffset = 0; } UNINIT_SESSION_SEND( pSession ); pSession++; } free( m_Sessions ); m_Sessions = NULL; LeaveCriticalSection( &m_SessionLock ); } VOID CRunDataProcesser::FreeRecvBuffers() { INT_PTR i; void **pBuffers; EnterCriticalSection( &m_RecvQueueLock ); pBuffers = *m_pRecvAppendList; for ( i=m_pRecvAppendList->count()-1; i>-1; --i ) { free( pBuffers[i] ); } m_pRecvAppendList->clear(); pBuffers = *m_pRecvProcList; for ( i=m_pRecvProcList->count()-1; i>-1; --i ) { free( pBuffers[i] ); } m_pRecvProcList->clear(); LeaveCriticalSection( &m_RecvQueueLock ); } VOID CRunDataProcesser::FreeSendBuffers(PRUNDATASENDTHREAD pSendThread) { INT_PTR i; void **pBuffers; EnterCriticalSection( &pSendThread->SendQueueLock ); pBuffers = *pSendThread->pSendAppendList; for ( i=pSendThread->pSendAppendList->count()-1; i>-1; --i ) { free( pBuffers[i] ); } pSendThread->pSendAppendList->clear(); pBuffers = *pSendThread->pSendProcList; for ( i=pSendThread->pSendProcList->count()-1; i>-1; --i ) { free( pBuffers[i] ); } pSendThread->pSendProcList->clear(); LeaveCriticalSection( &pSendThread->SendQueueLock ); } /* BOOL CRunDataProcesser::OpenServerPipe() { int nErr; while ( TRUE ) { m_hPipe = CreateFile( m_sPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if ( m_hPipe != INVALID_HANDLE_VALUE ) return TRUE; nErr = GetLastError(); if ( nErr != ERROR_PIPE_BUSY ) { GotError( __FUNCTION__, "CreateFile", nErr ); break; } if ( !WaitNamedPipe( m_sPipeName, 10000 ) ) { nErr = GetLastError(); GotError( __FUNCTION__, "WaitNamedPipe", nErr ); break; } } return FALSE; } VOID CRunDataProcesser::CloseServerPipe() { if ( m_hPipe != INVALID_HANDLE_VALUE ) { CloseHandle( m_hPipe ); m_hPipe = INVALID_HANDLE_VALUE; } } VOID CRunDataProcesser::ServerPipeError() { if ( m_hPipe != INVALID_HANDLE_VALUE ) { CancelRemainSendSessionBuffers(); CloseHandle( m_hPipe ); m_hPipe = INVALID_HANDLE_VALUE; //CloseAllSessions 必须在CloseHandle之后调用,否则CloseAllSessions->SendServerMessage->ServerPipeError 造成栈溢出 CloseAllSessions( TRUE ); } } */ BOOL CRunDataProcesser::CopyWaitSendBuffers(PRUNDATASENDTHREAD pSendThread, BOOL boForceCopy) { PSENDCLIENTBUF pSendBuf, *ppBufers; CBaseList *pBufferList; PRUNGATEUSERSESSION pSession; INT_PTR nCount, nSize, nTotalSize, nAppendSize; TICKCOUNT dwMsgTick; if ( !boForceCopy ) boForceCopy = TryEnterCriticalSection( &pSendThread->SendQueueLock ); else EnterCriticalSection( &pSendThread->SendQueueLock ); if ( boForceCopy ) { pBufferList = pSendThread->pSendAppendList; pSendThread->pSendAppendList = pSendThread->pSendProcList; pSendThread->pSendProcList = pBufferList; LeaveCriticalSection( &pSendThread->SendQueueLock ); nCount = pBufferList->count(); if ( nCount > 0 ) { dwMsgTick = _getTickCount(); ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList); nTotalSize = 0; nAppendSize = 0; do { pSendBuf = *ppBufers; ppBufers++; nCount--; pSession = pSendBuf->pSession; if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { nSize = pSession->SendBuf.nOffset + pSendBuf->nBufferSize + 1; if ( pSession->SendBuf.nSize < nSize ) { nSize = (nSize / SESSION_DATAGROW_SIZE + 1) * SESSION_DATAGROW_SIZE; pSession->SendBuf.nSize = (INT)nSize; pSession->SendBuf.lpBuffer = (char*)realloc( pSession->SendBuf.lpBuffer, nSize ); } memcpy( &pSession->SendBuf.lpBuffer[pSession->SendBuf.nOffset], pSendBuf + 1, pSendBuf->nBufferSize ); pSession->SendBuf.nOffset += pSendBuf->nBufferSize; pSession->SendBuf.lpBuffer[pSession->SendBuf.nOffset] = 0; pSession->dwServerMsgTick = dwMsgTick; nAppendSize += pSendBuf->nBufferSize; } nTotalSize += pSendBuf->nBufferSize; free( pSendBuf ); } while ( nCount > 0 ); pBufferList->clear(); // 原子操作 InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, (LONG)nAppendSize ); InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, -(INT)nTotalSize ); } } return boForceCopy; } VOID CRunDataProcesser::GetSessionLoginInfo(PRUNGATEUSERSESSION pSession, char *sBuffer, int nBufferSize) { } VOID CRunDataProcesser::GotError(LPCSTR sErrFn, LPCSTR sErrApi, int nErr) { OutputMsg( rmError, _T("CRunDataProcesser::%s Got Error %d on api \"%s\""), sErrFn, nErr, sErrApi ); } VOID CRunDataProcesser::InitSendThreadData() { int i; for ( i=0; i(); m_SendThreads[i].pSendProcList = new CBaseList(); } } VOID CRunDataProcesser::UninitSendThreadData() { int i; for ( i=0; iGetBindPort(); SendServerMessage(GM_GATEUSERINFO, 0, 0, 0, (char *)&gi, sizeof(GATEUSERINFO)); } VOID CRunDataProcesser::SendOpenSession(PRUNGATEUSERSESSION pSession) { char sRemoteAddr[32]; strcpy( sRemoteAddr, inet_ntoa( pSession->SockAddr.sin_addr ) ); SendServerMessage( GM_OPEN, pSession->nIndex, pSession->nSocket, 0, sRemoteAddr, (int)strlen(sRemoteAddr) + 1 ); OutputMsg(rmTip, _T("SendOpenSession: socket=%d sessionId=%d, remoteAddr=%s"), (int)pSession->nSocket, (int)pSession->nIndex, sRemoteAddr); } VOID CRunDataProcesser::SendCloseSession(PRUNGATEUSERSESSION pSession, BOOL boCloseOnServer, INT nReason) { PCLIENTRECVBUF pRecvBuf; int nSocket; if ( !pSession->boMarkToClose && pSession->nSocket != INVALID_SOCKET ) { OutputMsg( rmWaning, "关闭会话 socket=%d, sessionId=%d, serverId=%d,reasonId=%d,nVerifyIdx=%ld", (int)pSession->nSocket, (int)pSession->nIndex, (int)pSession->nServerIdx, nReason, pSession->nVerifyIdx ); pSession->boMarkToClose = true; nSocket = (int)pSession->nSocket; pSession->nSocket = INVALID_SOCKET; pSession->dwCloseTick = _getTickCount(); pSession->nVerifyIdx = 0; bool isInCommu =( pSession->nSessionSatus == enCommunication); //当前是否在通信状态 pSession->nSessionSatus = enSessionStatusIdle; //初始化状态 if (nSocket!=INVALID_SOCKET) closesocket( nSocket ); //如果需要向服务器发送关闭用户的消息则将消息添加到队列 //并且需要通信状态了,否则不需要发包,说明还没有通过验证 if ( boCloseOnServer && isInCommu ) { SendServerMessage( GM_CLOSE, 0, nSocket, 0, NULL, 0 ); } m_nActiveUser--; } } VOID CRunDataProcesser::SendKeepAliveAck(PRUNGATEUSERSESSION pSession, const char *pBuffer, SIZE_T nBufSize) { SendServerMessage(GM_APPKEEPALIVEACK, pSession->nIndex, pSession->nSocket, pSession->nServerIdx, (char *)pBuffer, (int)nBufSize); } VOID CRunDataProcesser::CloseAllSessions(BOOL boForceClose) { int i; TICKCOUNT dwCurTick; PRUNGATEUSERSESSION pSession; if ( !m_Sessions ) return; pSession = m_Sessions; EnterCriticalSection( &m_SessionLock ); EnterCriticalSection( &m_RecvQueueLock ); for ( i=0; inSocket != INVALID_SOCKET ) { if ( boForceClose ) { OutputMsg(rmTip,_T("CRunDataProcesser::CloseAllSessions close socket=%d"),(int)pSession->nSocket); SendCloseSession( pSession, TRUE, enReasonAllSessionClose ); //closesocket( pSession->nSocket ); pSession->boMarkToClose = true; pSession->boRemoteClosed = true; pSession->dwCloseTick = 0; pSession->nSocket = INVALID_SOCKET; pSession->nVerifyIdx = 0; m_nActiveUser--; if ( pSession->RecvBuf.lpBuffer ) { free( pSession->RecvBuf.lpBuffer ); pSession->RecvBuf.lpBuffer = NULL; } pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0; if ( pSession->SendBuf.lpBuffer ) { free( pSession->SendBuf.lpBuffer ); pSession->SendBuf.lpBuffer = NULL; } pSession->SendBuf.nSize = pSession->SendBuf.nOffset = 0; } else SendCloseSession( pSession, TRUE, enReasonAllSessionClose ); } pSession++; } for ( i=0; i *pBufferList; INT_PTR i, nCount, nTotalSize; nTotalSize = 0; for ( i=0; icount(); if ( nCount ) { ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList); do { pSendBuf = *ppBufers; ppBufers++; nCount--; nTotalSize += pSendBuf->nBufferSize; free( pSendBuf ); } while ( nCount > 0 ); pBufferList->clear(); } pBufferList = m_SendThreads[i].pSendAppendList; nCount = pBufferList->count(); if ( nCount ) { ppBufers = (PSENDCLIENTBUF*)(void**)(*pBufferList); do { pSendBuf = *ppBufers; ppBufers++; nCount--; nTotalSize += pSendBuf->nBufferSize; free( pSendBuf ); } while ( nCount > 0 ); pBufferList->clear(); } LeaveCriticalSection( &m_SendThreads[i].SendQueueLock ); } InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, -(INT)nTotalSize ); } BOOL CRunDataProcesser::CheckCloseSessions(BOOL boForceCheck) { static const DWORD dwCloseIdleSessionLong = 10 * 60 * 1000; int i, boResult; TICKCOUNT dwCurTick; PRUNGATEUSERSESSION pSession; if ( boForceCheck ) { EnterCriticalSection( &m_SessionLock ); boResult = TRUE; } else boResult = TryEnterCriticalSection( &m_SessionLock ); if ( boResult ) { dwCurTick = _getTickCount(); pSession = m_Sessions - 1; for ( i=0; iboMarkToClose || pSession->boRemoteClosed ) { //加上pSession->dwCloseTick非0判断,防止内存错误 //可能的原因是标记pSession->boMarkToClose或pSession->boRemoteClosed为true的线程尚未来得及 //给pSession->dwCloseTick赋值,而此线程恰好已经执行到此处对pSession的资源进行释放,从而 //造成内存错误。 if ( pSession->dwCloseTick && dwCurTick - pSession->dwCloseTick >= 10 * 1000 ) { if(pSession->nSocket != INVALID_SOCKET) { OutputMsg( rmWaning, "Socket%d 标记为删除",(int)pSession->nSocket ); } LOCK_SESSION_SEND( pSession ); pSession->nSocket = INVALID_SOCKET; pSession->nVerifyIdx = 0; if ( pSession->RecvBuf.lpBuffer ) { free( pSession->RecvBuf.lpBuffer ); pSession->RecvBuf.lpBuffer = NULL; } pSession->RecvBuf.nSize = pSession->RecvBuf.nOffset = 0; if ( pSession->SendBuf.lpBuffer ) { free( pSession->SendBuf.lpBuffer ); pSession->SendBuf.lpBuffer = NULL; } pSession->SendBuf.nSize = 0;//SendBuf.nOffset值由发送线程维护 pSession->boMarkToClose = false; pSession->boRemoteClosed = false; pSession->dwCloseTick = 0; UNLOCK_SESSION_SEND( pSession ); } } else if ( pSession->nSocket != INVALID_SOCKET ) { if (dwCurTick - pSession->dwClientMsgTick >= dwCloseIdleSessionLong) { OutputMsg( rmWaning, "客户端Idle,dwCurTick=%ld,dwClientMsgTick=%ld",(long long)dwCurTick, (long)pSession->dwClientMsgTick); SendCloseSession( pSession, TRUE, enReasonIdle ); } if(dwCurTick - pSession->dwServerMsgTick >= dwCloseIdleSessionLong) { //OutputMsg( rmWaning, "服务器较长时间处于非活动状态的会话,关闭会话" ); //OutputMsg( rmWaning, "服务器端idle,dwCurTick=%I64d,dwClientMsgTick=%I64d",(long long)dwCurTick, (long long)pSession->dwServerMsgTick); //SendCloseSession( pSession, TRUE, enReasonIdle ); } } } LeaveCriticalSection( &m_SessionLock ); } return boResult; } char* getDescBySysId(int id) { switch (id) { case 0: return "默认系统"; break; case 1: return "移动系统"; break; case 2: return "属性系统"; break; case 3: return "观察系统"; break; case 4: return "Buff系统"; break; case 5: return "技能系统"; break; case 6: return "任务系统"; break; case 7: return "装备系统"; break; case 8: return "背包系统"; break; case 9: return "聊天系统"; break; case 10: return "帮会系统"; break; case 11: return "技能标记"; break; case 12: return "商城系统"; break; case 13: return "交易系统"; break; case 14: return "玩家变量"; break; case 15: return "拾取系统"; break; case 16: return "队伍系统"; break; case 17: return "操练系统"; break; case 18: return "兵魂系统"; break; case 20: return "副本系统"; break; case 21: return "交互系统"; break; case 22: return "消息系统"; break; case 23: return "仓库系统"; break; case 24: return "PK系统"; break; case 26: return "杂七杂八"; break; case 27: return "交易行"; break; case 28: return "成就系统"; break; case 30: return "特效系统"; break; case 34: return "宠物系统"; break; case 35: return "交通工具"; break; case 36: return "盗梦空间"; break; case 39: return "摆摊系统"; break; case 41: return "好友系统"; break; case 43: return "宝石系统"; break; case 44: return "英雄系统"; break; case 45: return "载具系统"; break; case 49: return "BOSS系统"; break; case 50: return "邮件系统"; break; case 51: return "衣橱系统"; break; case 52: return "加速外挂"; break; case 54: return "新头衔"; break; case 57: return "职业竞技"; break; case 128: return "脚本"; break; case 129: return "NPC交易"; break; case 130: return "装备修理"; break; case 134: return "技能快捷键"; break; case 137: return "内劲系统"; break; case 138: return "福利系统"; break; case 139: return "脚本乱七八糟"; break; case 140: return "功勋系统"; break; case 145: return "活动系统"; break; case 255: return "登陆系统"; break; default: return "错误!"; break; } } VOID CRunDataProcesser::CheckSendSessionBuffers(PRUNDATASENDTHREAD pSendThread) { DECLARE_FUN_TIME_PROF(); static char sSendCheckBuf[RUNGATE_ONCESENDUSE_LIMIT]; int nErr, nRemainSize; char *pBuffer; PRUNGATEUSERSESSION pSession = &m_Sessions[pSendThread->nThreadIdx]; pSendThread->boSendEWouldBlock = false; pSendThread->boSendFewBuffer = false; for ( ;pSession <= &m_Sessions[m_nMaxSessionCount-1]; pSession += m_nSendThreadCount ) { if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed ) { if ( !pSession->boSendAvaliable ) { if ( _getTickCount() >= pSession->dwSendTimeOut ) { pSession->boSendAvaliable = true; pSession->dwSendTimeOut = 0; } else continue; } if ( TRYLOCK_SESSION_SEND( pSession ) ) { nRemainSize = pSession->SendBuf.nOffset; if ( nRemainSize > 4096 * 1024 ) { SendCloseSession( pSession, TRUE, enReasonSenderBuffLarge ); nRemainSize = 0; OutputMsg( rmWaning, "关闭了一个发送数据队列大于4MB的连接。" ); } if ( nRemainSize ) { pBuffer = pSession->SendBuf.lpBuffer; if ( nRemainSize >= MAXINT )//不让它执行这段代码 { sSendCheckBuf[0] = '*'; memcpy( &sSendCheckBuf[1], pBuffer, RUNGATE_ONCESENDUSE_LIMIT -1 ); nErr = ::send( pSession->nSocket, sSendCheckBuf, RUNGATE_ONCESENDUSE_LIMIT, 0 ); if ( nErr > 0 ) { if ( nErr != RUNGATE_ONCESENDUSE_LIMIT ) pSendThread->boSendFewBuffer = true; InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -(nErr - 1) ); InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nErr ); nRemainSize -= nErr - 1; memcpy( pBuffer, &pBuffer[nErr - 1], nRemainSize ); pSession->SendBuf.nOffset = nRemainSize; pBuffer[nRemainSize] = 0; pSession->nSendPacketCount++; } else if ( !nErr || WSAGetLastError() != WSAEWOULDBLOCK ) { InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -pSession->SendBuf.nOffset ); pSession->boRemoteClosed = true; pSession->SendBuf.nOffset = 0; SendCloseSession( pSession, TRUE, enReasonSocketError ); } else { pSession->boSendAvaliable = false; pSession->dwSendTimeOut = _getTickCount() + RUNGATE_SENDCHECK_TIMEOUT; pSendThread->boSendEWouldBlock = true; } } else { TICKCOUNT nCurTick = _getTickCount(); if (nCurTick < pSession->nLastSendPacketTime) pSession->nLastSendPacketTime = 0; if (nCurTick - pSession->nLastSendPacketTime >= 15) { pSession->nLastSendPacketTime = nCurTick; nErr = ::send( pSession->nSocket, pBuffer, nRemainSize, 0 ); if ( nErr > 0 ) { pSession->nSendPacketCount++; InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nErr ); InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nErr ); if ( nErr < nRemainSize ) { pSendThread->boSendFewBuffer = true; memcpy( pBuffer, &pBuffer[nErr], nRemainSize - nErr ); nRemainSize -= nErr; pBuffer[nRemainSize] = 0; pSession->SendBuf.nOffset = nRemainSize; pSession->nTimeStampOffset = nRemainSize; } else { pBuffer[0] = 0; pSession->SendBuf.nOffset = 0; pSession->nTimeStampOffset = 0; } #ifdef _DEBUG_GATEMSG char * pIp = inet_ntoa(pSession->SockAddr.sin_addr); OutputMsg( rmTip, "[%s]Idx=%d: 发到客户端, 已发长度%d, 剩余待发%d;", pIp, pSession->nVerifyIdx, nErr, pSession->SendBuf.nOffset); #endif } else { int nErrorId = WSAGetLastError(); if ( !nErr || nErrorId != WSAEWOULDBLOCK ) { OutputMsg(rmWaning,"Socket =%d,send fail, errorid=%d ",(int)pSession->nSocket,nErrorId); InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nRemainSize ); InterlockedExchangeAdd( (LONG*)&m_dwSendUserSize, nRemainSize ); pBuffer[0] = 0; pSession->SendBuf.nOffset = 0; } else { pSession->boSendAvaliable = false; pSession->dwSendTimeOut = _getTickCount() + RUNGATE_SENDCHECK_TIMEOUT; pSendThread->boSendEWouldBlock = true; } } } } } UNLOCK_SESSION_SEND( pSession ); } } else { //会话关闭后减少待发送数据统计值 if ( nRemainSize = pSession->SendBuf.nOffset ) { InterlockedExchangeAdd( (LONG*)&m_dwWaitSendUserSize, -nRemainSize ); pSession->SendBuf.nOffset = 0; } } } } //发送数据到服务器 VOID CRunDataProcesser::SendServerMessage(int nIdent, int nSessionIdx, SOCKET nSocket, int nServerIdx, char *pBuffer, int nBufSize) { if ( !connected() ) return; PutMessage(nIdent, nSessionIdx, nSocket, nServerIdx, m_llSvrTimeDiff, pBuffer, nBufSize); /* if (GM_CHECKCLIENT != nIdent && GM_CHECKSERVER != nIdent && GM_DATA != nIdent) { TRACE( _T("向后台发送命令CMD=%d,socketID=%d,nSessionIdx=%d,nServerIdx=%d\n"), nIdent,nSocket,nSessionIdx,nServerIdx); } if (nIdent == GM_DATA) { OutputMsg( rmTip, _T("向后台发送数据size=%d,nSocket=%d,nSessionIdx=%d,nServerIdx=%d"),nBufSize,nSocket,nSessionIdx,nServerIdx); } */ /* --begin 老的发送给服务器数据代码 //这个是消息头 RUNGATEMSGHDR Hdr; Hdr.dwGateCode = RUNGATECODE; Hdr.nSocket = nSocket; Hdr.wSessionIdx = nSessionIdx; Hdr.wIdent = nIdent; Hdr.wServerIdx = nServerIdx; Hdr.nDataSize = nBufSize; Hdr.tickCount = m_llSvrTimeDiff + _getTickCount(); SIZE_T headSize = sizeof(Hdr); CDataPacket &packet = allocSendPacket(); packet << Hdr; packet.writeBuf(pBuffer, nBufSize); flushSendPacket(packet); ---end of 老的发送数据给服务器代码 */ /* char buff [MAX_SEND_BUFF_SIZE]; size_t headSize = sizeof(Hdr); size_t totalSize = headSize + nBufSize; if (totalSize > MAX_SEND_BUFF_SIZE) { GotError( __FUNCTION__, _T("发送包的长度过大"), nBufSize ); return; } memcpy(buff,&Hdr,headSize); memcpy((buff+headSize),pBuffer,nBufSize); */ //AppendSendBuffer(&Hdr,headSize ); //AppendSendBuffer(pBuffer,nBufSize ); /* 这里使用的是pipe,修改为socket发送 RUNGATEMSGHDR Hdr; DWORD dwBytesWriten; if ( m_hPipe != INVALID_HANDLE_VALUE ) { Hdr.dwGateCode = RUNGATECODE; Hdr.nSocket = nSocket; Hdr.wSessionIdx = nSessionIdx; Hdr.wIdent = nIdent; Hdr.wServerIdx = nServerIdx; Hdr.nDataSize = nBufSize; #pragma __CPMSG__("----------------修改此处WriteFile为Socket的AppendSendData") if ( !WriteFile( m_hPipe, &Hdr, sizeof(Hdr), &dwBytesWriten, NULL ) ) { GotError( __FUNCTION__, "WriteFile", GetLastError() ); ServerPipeError(); } else if ( nBufSize > 0 && !WriteFile( m_hPipe, pBuffer, nBufSize, &dwBytesWriten, NULL ) ) { GotError( __FUNCTION__, "WriteFile", GetLastError() ); ServerPipeError(); } } */ } /* * 解包WebSocket数据 * param[in] pSession 用户会话 * param[] pInBuff 输入的数据包 * param[] nInSize 输入的数据包的长度 * param[] pOutBuff 输出的数据包指针 * param[] nOutSize 输出的数据包的长度 * param[] nInProcessSize 输入的数据包处理了的长度,如果大于0,那么前面的这个字节的数据包可以丢弃了 * param[] nOutProcessSize 处理好的数据长度,处理好的数据放在pOutBuff里 * ret 如果进行了数据处理返回true,否则返回false。数据处理包括发现前面有无效数字,拷贝了一个完整的数据包,丢弃一些字节等 */ static bool WebSocketDataUnpack(PRUNGATEUSERSESSION pSession, char* pInBuff, SIZE_T nInSize, char* pOutBuff, SIZE_T nOutSize, SIZE_T& nInProcessSize, SIZE_T& nOutProcessSize) { pSession->webSocketHead.reset(); nInProcessSize = 0; nOutProcessSize = 0; if (NULL == pInBuff || NULL == pOutBuff) return false; char* pdata = pInBuff; SIZE_T nLeftSize = nInSize; #define WEBSOCKET_READ(_TYPE) *((_TYPE*)pdata); nLeftSize -= sizeof(_TYPE); pdata += sizeof(_TYPE) //读取websocket固定包头 if (!pSession->webSocketHead.rh) { //长度不满足 if (nLeftSize < 2) return false; //读取 uint8_t head = WEBSOCKET_READ(uint8_t); pSession->webSocketHead.fin = head >> 7; pSession->webSocketHead.opcode = emOpcode(head & 0xF); head = WEBSOCKET_READ(uint8_t); pSession->webSocketHead.len = head & 0x7F; pSession->webSocketHead.mask = head >> 7; pSession->webSocketHead.rh = 1;//标记头部读取完成 nInProcessSize += 2;//记录处理长度 } //读取长度 if (!pSession->webSocketHead.rl) { uint8_t nsize = pSession->webSocketHead.GetLenNeedByte(); if (nsize) { //这个包不够一个长度 if (nLeftSize < nsize) return false; if (nsize == 2) { pSession->webSocketHead.ex_len.v16 = WEBSOCKET_READ(uint16_t); pSession->webSocketHead.ex_len.v16 = ntohs(pSession->webSocketHead.ex_len.v16); nInProcessSize += 2; //记录处理长度 } else { pSession->webSocketHead.ex_len.v64 = WEBSOCKET_READ(uint64_t); pSession->webSocketHead.ex_len.v64 = ntohl((u_long)pSession->webSocketHead.ex_len.v64); nInProcessSize += 8; //记录处理长度 } } pSession->webSocketHead.rl = 1; } //读取MKEY if (!pSession->webSocketHead.rk) { if (pSession->webSocketHead.mask) { //这个包不够一个key长度 if (nLeftSize < 4) return false; pSession->webSocketHead.mkey[0] = WEBSOCKET_READ(uint8_t); pSession->webSocketHead.mkey[1] = WEBSOCKET_READ(uint8_t); pSession->webSocketHead.mkey[2] = WEBSOCKET_READ(uint8_t); pSession->webSocketHead.mkey[3] = WEBSOCKET_READ(uint8_t); nInProcessSize += 4; //记录处理长度 } pSession->webSocketHead.rk = 1; } //读取数据段 uint64_t data_len = pSession->webSocketHead.GetLen(); if (nLeftSize < data_len) return false; // 掩码处理 if (pSession->webSocketHead.mask) { char* dptr = pdata; for (size_t i = 0; i < data_len; ++i) { dptr[i] = dptr[i] ^ pSession->webSocketHead.mkey[i % 4]; } } memcpy(pOutBuff,(void *)(pInBuff + nInProcessSize), data_len); //OutputMsg( rmTip, "Websocket数据(头长:%ld, 数据长:%ld)", nInProcessSize, data_len, *((int*)pInBuff)); nInProcessSize += data_len; nOutProcessSize = data_len; return true; } //收到用户的数据包 VOID CRunDataProcesser::ProcessUserRecvPacket(PRUNGATEUSERSESSION pSession, char *pBuffer, int nBufferSize) { DECLARE_FUN_TIME_PROF(); //static const char szFlashSocketPolicyRequest[] = ""; //static const char szFlashSocketPolicyRequestReply[]= ""; //static int s_policyStrLen = (int)strlen(szFlashSocketPolicyRequest) +1; //请求安全策略文件的长度,后面都是以\0结尾的 //static int s_policyReplyStrLen = (int)strlen(szFlashSocketPolicyRequestReply) +1;//回复安全策略文件的长度 InterlockedExchangeAdd( (LONG*)&m_dwProcessRecvSize, nBufferSize ); //session中已缓存的数据(剩下待处理的数据) int nLeftDataSize = pSession->RecvBuf.nOffset + nBufferSize + 1; if ( pSession->RecvBuf.nSize < nLeftDataSize ) { pSession->RecvBuf.nSize = (nLeftDataSize / SESSION_DATAGROW_SIZE + 1) * SESSION_DATAGROW_SIZE; pSession->RecvBuf.lpBuffer = (char*)realloc( pSession->RecvBuf.lpBuffer, pSession->RecvBuf.nSize ); } nLeftDataSize--; //将数据拷贝过来 char *pDataBuffer; pDataBuffer = pSession->RecvBuf.lpBuffer; memcpy( &pDataBuffer[pSession->RecvBuf.nOffset], pBuffer, nBufferSize ); pSession->RecvBuf.nOffset = nLeftDataSize; pDataBuffer[nLeftDataSize] = 0; //如果剩余数据超过峰值则丢弃 if ( pSession->RecvBuf.nOffset >= SESSION_MAX_RECVPROC_SIZE ) { pSession->RecvBuf.nOffset = 0; SendCloseSession( pSession, TRUE, enReasonLargePackLeft ); return; } //输出日志 #ifdef _DEBUG_GATEMSG //char * pIp = inet_ntoa(pSession->SockAddr.sin_addr); OutputMsg( rmTip, "Idx=%ld: 准备处理socket数据, session状态为%d, 当前接收缓存为%d;", pSession->nVerifyIdx, pSession->nSessionSatus, nLeftDataSize); #endif //SIZE_T nPolicyStrSize = (int)strlen(szFlashSocketPolicyRequest); //处理Session的buffer char pDataProcBuf[MAX_SEND_BUFF_SIZE]; #ifdef _DEBUG_GATEMSG memset(pDataProcBuf, 0, MAX_SEND_BUFF_SIZE); #endif while ( nLeftDataSize > 0 ) { if ( pSession->wPacketError >= SESSION_PACKETERR_MAX ) { nLeftDataSize = 0; SendCloseSession( pSession, TRUE, enReasonRecvLargerPack ); OutputMsg( rmWaning, "wPacketError=%d,超出了",pSession->wPacketError); break; } if ( pSession->boMarkToClose || pSession->boRemoteClosed ) { OutputMsg( rmTip, "远程关闭,不处理数据"); break; } SIZE_T nBuffSize = pSession->RecvBuf.nOffset ; //正常通信状态,这个最多放前面 if (pSession->nSessionSatus != enSessionStatusIdle) { SIZE_T nInprocessSize =0 ,nOutProcessSize =0; // Websocket数据解包处理 if (WebSocketDataUnpack(pSession, pDataBuffer, nLeftDataSize, pDataProcBuf, MAX_SEND_BUFF_SIZE, nInprocessSize, nOutProcessSize)) { // 调整已处理过的字节 if (nInprocessSize > 0) { nLeftDataSize -= (INT)nInprocessSize; if (nLeftDataSize < 0) { nLeftDataSize = 0; } else { pDataBuffer = (char *)(pDataBuffer + nInprocessSize); } } #ifdef _DEBUG_GATEMSG OutputMsg( rmTip, "Idx=%ld: 已处理%d, 协议有效长%d, 当前接收缓存为%d;", pSession->nVerifyIdx, nInprocessSize, nOutProcessSize, nLeftDataSize); #endif // 将输出的数据要传递到LogicServer if (nOutProcessSize > 0) { //正常通讯 if (pSession->nSessionSatus == enCommunication) { //检查退出 if (pSession->webSocketHead.opcode == emOpcode(0x8)) { OutputMsg( rmTip, "远程关闭,不处理数据"); SendCloseSession(pSession, TRUE, 1); return; } //检查服务端key if (nOutProcessSize >= 2) { unsigned short tag = *((unsigned short*)pDataProcBuf); if(tag != pSession->nKey) { SendCloseSession(pSession, TRUE, 2); return; } //截去key char* pOutData = (char*)pDataProcBuf + sizeof(unsigned short); nOutProcessSize -= sizeof(unsigned short); //截去验证 uint32_t check = *((uint32_t*)pOutData); pOutData = pOutData + sizeof(uint32_t); nOutProcessSize -= sizeof(uint32_t); //测试代码,数据转发给客户端 //PostUserServerData(pSession, pOutData, (INT)nOutProcessSize, TRUE, TRUE); #ifdef _DEBUG_GATEMSG OutputMsg( rmTip, "Idx=%ld: 准备发服务器 [%s] SysID:%d, CmdID:%d;", pSession->nVerifyIdx, getDescBySysId(*((unsigned char*)pOutData)), *((unsigned char*)pOutData), *((unsigned char*)pOutData + 1)); #endif //把数据发到服务器 SendServerMessage(GM_DATA, pSession->nIndex, pSession->nSocket, pSession->nServerIdx, pOutData, (INT)nOutProcessSize); //OutputMsg( rmTip, "systemID = %d", *((char*)(pOutData))); //OutputMsg( rmTip, "cmdID = %d", *((char*)(pOutData + 1))); } } //刚连上来 else if(pSession->nSessionSatus == enConn) { pSession->nKey = (unsigned short)wrand(INT_MAX); PostUserServerData(pSession, (char *)&pSession->nKey, 2); pSession->nSessionSatus = enCommunication; OutputMsg( rmTip, "=================================================Finish"); } } } else { OutputMsg( rmTip, "消息长度不够,等待下一次组包"); break; } } } //修正Session的buffer if (pSession->RecvBuf.lpBuffer != NULL) { if ( nLeftDataSize > 0 ) { if ( pDataBuffer != pSession->RecvBuf.lpBuffer ) { memcpy( pSession->RecvBuf.lpBuffer, &pSession->RecvBuf.lpBuffer[pSession->RecvBuf.nOffset - nLeftDataSize], nLeftDataSize ); pSession->RecvBuf.lpBuffer[nLeftDataSize] = 0; pSession->RecvBuf.nOffset = nLeftDataSize; } } else { pSession->RecvBuf.lpBuffer[0] = 0; pSession->RecvBuf.nOffset = 0; } } } int CRunDataProcesser::s_nIgnoreDataPacket = 0; VOID CRunDataProcesser::PostUserServerData(PRUNGATEUSERSESSION pSession, const char *pBuffer, int nBufferSize, BOOL boWriteWsHdr, BOOL boWriteProtoHdr, TICKCOUNT nSendTime) { /*if (s_nIgnoreDataPacket) { return; } */ //OutputMsg( rmTip, "向玩家发送%d个字节数据",nBufferSize); DECLARE_FUN_TIME_PROF(); char *pDataPtr; PRUNDATASENDTHREAD pSendThread; PSENDCLIENTBUF pSendBuf; PDATAHEADER pProtoHdr; static char sPrintS2CBuffer[81920]; pSendThread = &m_SendThreads[pSession->nIndex % m_nSendThreadCount]; pSendBuf = (PSENDCLIENTBUF)malloc( nBufferSize + sizeof(*pSendBuf) + 4 + sizeof(*pProtoHdr) + 16); pSendBuf->pSession = pSession; int wsheaderLength = 0; pDataPtr = (char*)(pSendBuf + 1); CDataPacket pack(pDataPtr, nBufferSize + 4 + sizeof(*pProtoHdr) + 16); pack.setPosition(0); // 写入websocket头部 if( boWriteWsHdr ) { int totallen = boWriteProtoHdr ? nBufferSize + sizeof(uint16_t) : nBufferSize; pack << (uint8_t)0x82;//写头部 //写长度 if (totallen >= 126) {//7位放不下 if (totallen <= 0xFFFF) {//16位放 pack << (uint8_t)126; pack << (uint16_t)htons((u_short)totallen); } else {//64位放 pack << (uint8_t)127; pack << (uint64_t)OrderSwap64(totallen); } } else { pack << (uint8_t)totallen; } } // 写入协议头部 if ( boWriteProtoHdr ) { //DATAHEADER ProtoHd; //ProtoHd.tag = DEFAULT_TAG_VALUE; //ProtoHd.len = nBufferSize; //ProtoHd.u.tp = nSendTime - m_llSvrTimeDiff; // 网关收到来自服务器的数据包,盖上时间戳 //ProtoHd.u.tp = __max(0, _getTickCount() - (nSendTime - m_llSvrTimeDiff)); //pack.writeBuf(&ProtoHd, sizeof(DATAHEADER)); //写数据 pack << (uint16_t)pSession->nKey; } //写数据 pack.writeBuf(pBuffer, nBufferSize); // 写入数据总长度 pack.setPosition(0); pSendBuf->nBufferSize = pack.getAvaliableLength(); #ifdef _DEBUG_GATEMSG OutputMsg( rmTip, "Idx=%d: 准备发客户端 [%s] SysID:%d, CmdID:%d, 数据长:%d, 协议有效长:%d", pSession->nVerifyIdx, getDescBySysId(*((unsigned char*)pBuffer)), *((unsigned char*)pBuffer), *((unsigned char*)pBuffer + 1), pSendBuf->nBufferSize, nBufferSize); #endif InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, nBufferSize ); EnterCriticalSection( &pSendThread->SendQueueLock ); pSendThread->pSendAppendList->add( pSendBuf ); LeaveCriticalSection( &pSendThread->SendQueueLock ); } /* VOID CRunDataProcesser::PostUserServerRawData(PRUNGATEUSERSESSION pSession, const char *pBuffer, DWORD dwBufferSize) { char *pDataPtr; PRUNDATASENDTHREAD pSendThread; PSENDCLIENTBUF pSendBuf; pSendThread = &m_SendThreads[pSession->nIndex % m_nSendThreadCount]; if (dwBufferSize > 0) { pSendBuf = (PSENDCLIENTBUF)malloc( sizeof(*pSendBuf) + dwBufferSize + 1 ); pSendBuf->pSession = pSession; pDataPtr = (char*)(pSendBuf + 1); memcpy( pDataPtr, pBuffer, dwBufferSize ); pDataPtr[dwBufferSize] = 0; pSendBuf->nBufferSize = dwBufferSize; InterlockedExchangeAdd( (LONG*)&m_dwWaitSendQueueSize, dwBufferSize ); } EnterCriticalSection( &pSendThread->SendQueueLock ); pSendThread->pSendAppendList->add( pSendBuf ); LeaveCriticalSection( &pSendThread->SendQueueLock ); } */ INT CRunDataProcesser::GetActiveUserCount() { return m_nActiveUser; } VOID CRunDataProcesser::SetName(LPCSTR sName) { ZeroMemory( m_sGateName, sizeof(m_sGateName) ); strncpy( m_sGateName, sName, __min(sizeof(m_sGateName)-1, strlen(sName)) ); SetClientName(sName); } /* VOID CRunDataProcesser::SetPipeName(LPCSTR sPipeName) { ZeroMemory( m_sPipeName, sizeof(m_sPipeName) ); strncpy( m_sPipeName, sPipeName, __min(sizeof(m_sPipeName)-1, strlen(sPipeName)) ); } */ INT CRunDataProcesser::GetSendThreadCount() { return m_nSendThreadCount; } VOID CRunDataProcesser::SetSendThreadCount(INT ThreadCount) { if ( !m_boStarted && ThreadCount > 0 && ThreadCount <= RUNDATA_MAX_SENDTHREAD ) { m_nSendThreadCount = ThreadCount; } } DATAPROCESSERTYPE CRunDataProcesser::GetDataProcessType() { return m_DataProcessType; } VOID CRunDataProcesser::SetDataProcessType(DATAPROCESSERTYPE Type) { m_DataProcessType = Type; } VOID CRunDataProcesser::SetRunSockProcesser(CRunSockProcesser* pSockProcesser) { m_pSockProcesser = pSockProcesser; } INT CRunDataProcesser::GetMaxSessionCount() { return m_nMaxSessionCount; } PRUNDATASENDTHREAD CRunDataProcesser::GetSendThreadInfo(INT ThreadIdx) { if ( ThreadIdx >= 0 && ThreadIdx < RUNDATA_MAX_SENDTHREAD ) { if ( m_SendThreads[ThreadIdx].hThread ) return &m_SendThreads[ThreadIdx]; } return NULL; } PRUNGATEUSERSESSION CRunDataProcesser::GetFirstSession() { return m_Sessions; } VOID CRunDataProcesser::SetPrintC2SMessage(const BOOL boPrint) { m_boPrintC2SMsg = boPrint; } VOID CRunDataProcesser::SetPrintS2CMessage(const BOOL boPrint) { m_boPrintS2CMsg = boPrint; } BOOL CRunDataProcesser::Startup() { int i; m_boStoping = FALSE; m_dwWaitSendUserSize = 0; m_dwWaitSendQueueSize = 0; m_dwLastProcUsrMsgTime = 0; m_dwLastProcSrvMsgTime = 0; m_dwLastRecvSrvMsgTime = 0; m_dwRecvSeverSize = 0; m_dwSendUserSize = 0; m_dwProcSrvThreadSleep = 0; m_dwSendQueueSize = 0; //初始化会话队列 InitSessions(); //创建用户数据处理线程 #ifdef _MSC_VER m_hProcRecvThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)RecvDataProcessRoutine, this, 0, NULL ); if ( !m_hProcRecvThread ) { GotError( __FUNCTION__, _T("CreateThread"), GetLastError() ); return FALSE; } #else if (pthread_create(&m_hProcRecvThread, NULL, RecvDataProcessRoutine, this)) { return FALSE; } #endif //创建用户数据发送线程 for ( i=0; iGetName()); nLine++; ChangeConsoleLine( nLine, 0, "活动连接数:%d \n", pRunData->GetActiveUserCount() ); nLine++; ChangeConsoleLine( nLine, 0, "接收用户数据: %dB 发送用户数据: %dKB 待发用户数据: %dKB 待发用户队列: %dKB \n", pRunData->m_dwProcessRecvSize, pRunData->m_dwSendUserSize / 1024, pRunData->m_dwWaitSendUserSize / 1024, pRunData->m_dwSendQueueSize / 1024 ); nLine++; ChangeConsoleLine( nLine, 0, "接收引擎数据: %dKB 接收数据时间: %d毫秒 引擎数据处理: %d毫秒 用户数据处理: %d毫秒 \n", pRunData->m_dwRecvSeverSize / 1024, pRunData->m_dwLastRecvSrvMsgTime, pRunData->m_dwLastProcSrvMsgTime, pRunData->m_dwLastProcUsrMsgTime ); nLine++; for ( i=0; iGetSendThreadInfo( i ); if ( !pSendThread ) continue; ChangeConsoleLine( nLine, 0, "发送线程%d[数据处理: %d毫秒 休眠时间: %d毫秒 标志:%d/%d] \n", i, pSendThread->dwProcTick, pSendThread->dwSleepTick, pSendThread->boSendEWouldBlock, pSendThread->boSendFewBuffer ); nLine++; InterlockedExchange( (LONG*)&pSendThread->dwProcTick, 0 ); InterlockedExchange( (LONG*)&pSendThread->dwSleepTick, 0 ); } ChangeConsoleLine( nLine, 0, "服务器数据处理线程休眠: %d毫秒\n", pRunData->m_dwProcSrvThreadSleep ); nLine++; ChangeConsoleLine( nLine, 0, "----------------------------------------------------------------\n" ); nLine++; pRunData->Dump(); InterlockedExchange( (LONG*)&pRunData->m_dwProcessRecvSize, 0 ); InterlockedExchange( (LONG*)&pRunData->m_dwSendUserSize, 0 ); InterlockedExchange( (LONG*)&pRunData->m_dwRecvSeverSize, 0 ); } VOID CRunDataProcesser::Stop() { int i; m_boStoping = TRUE; Inherited::Stop(); CloseThread( m_hProcRecvThread ); for ( i=0; inSocket == INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed && !pSession->dwCloseTick && pSession->nSessionSatus ==enSessionStatusIdle) { pNewSession = pSession; pNewSession->SendBuf.nOffset = 0; pNewSession->dwCloseTick = 0; pNewSession->boMarkToClose = false; pNewSession->boRemoteClosed = false; pNewSession->nSessionSatus = enConn; break; } pSession++; } LeaveCriticalSection( &m_SessionLock ); if ( pNewSession ) { pNewSession->SockAddr = RemoteAddr; pNewSession->nServerIdx = 0; pNewSession->btPacketIdx = 0; pNewSession->wPacketError = 0; pNewSession->nRecvPacketCount=0; pNewSession->nSendPacketCount=0; pNewSession->boMarkToClose = false; pNewSession->boRemoteClosed = false; pNewSession->boSendAvaliable= true; pNewSession->dwSendTimeOut = 0; pNewSession->dwCloseTick = 0; pNewSession->dwConnectTick = _getTickCount(); pNewSession->dwClientMsgTick= pNewSession->dwConnectTick; pNewSession->dwServerMsgTick= pNewSession->dwConnectTick; pNewSession->nVerifyIdx = InterlockedIncrement( (unsigned long long*)&m_nUserVerify ); pNewSession->webSocketHead.reset(); pNewSession->webSocketShakeHand = false; pNewSession->sLoginAccount[0] = 0; pNewSession->sLoginCharName[0]= 0; //pNewSession->nSessionId = 0; if ( !pNewSession->RecvBuf.lpBuffer ) { pNewSession->RecvBuf.nSize = SESSION_RECV_BUFSIZE ; pNewSession->RecvBuf.lpBuffer = (char*)malloc( pNewSession->RecvBuf.nSize ); } pNewSession->RecvBuf.nOffset = 0; #ifdef WIN32 pNewSession->Overlapped.WSABuf.buf = pNewSession->sRecvBuf; pNewSession->Overlapped.WSABuf.len = sizeof(pNewSession->sRecvBuf) - 1; #endif pNewSession->sRecvBuf[sizeof(pNewSession->sRecvBuf)] = 0; if ( !pNewSession->SendBuf.lpBuffer ) { pNewSession->SendBuf.nSize = SESSION_SEND_BUFSIZE ; pNewSession->SendBuf.lpBuffer = (char*)malloc( pNewSession->SendBuf.nSize ); } pNewSession->SendBuf.nOffset = 0; //最后设置会话的nSocket成员数据, //以防止其他线程通过nSocket != INVALID_SOCKET判断后对一个尚为初始化完毕的会话进行操作! pNewSession->nSocket = nSocket; pNewSession->nSessionSatus = enConn; //开始处于连接状态 char * pIp = inet_ntoa(RemoteAddr.sin_addr); OutputMsg( rmTip, "[%s]接入新的socket=%d 完毕,nVerifyIdx=%ld",pIp, (int)nSocket,pNewSession->nVerifyIdx); m_nActiveUser++; //增加活动用户计数 struct timeval tv_timeout; tv_timeout.tv_sec = 10; tv_timeout.tv_usec = 0; setsockopt(nSocket,SOL_SOCKET,SO_RCVTIMEO,&tv_timeout, sizeof(tv_timeout)); setsockopt(nSocket,SOL_SOCKET,SO_SNDLOWAT,&tv_timeout, sizeof(tv_timeout)); int nErr = ::recv(pNewSession->nSocket, pNewSession->sRecvBuf, sizeof(pNewSession->sRecvBuf)-1, 0); if ( nErr > 0 ) { pNewSession->sRecvBuf[nErr] = 0; AddRecvBuf( pNewSession, pNewSession->nVerifyIdx, pNewSession->sRecvBuf, nErr ); } else if (nErr == SOCKET_ERROR) { pNewSession->boRemoteClosed = true; SendCloseSession( pNewSession, TRUE, 2002 ); } } return pNewSession; } static bool gFindHttpParam(const char * param, const char * buf) { while (*param == *buf) { if (*(param + 1) == '\0') return true; ++param; ++buf; } return false; } #define WEB_SOCKET_HANDS_RE "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n" #define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" VOID CRunDataProcesser::ShakeHandsHandle(PRUNGATEUSERSESSION pSession, char* pBuffer, int BufferSize) { char key[512]; memset(key, 0, 512); for (int i = 0; i < BufferSize; ++i) { if (gFindHttpParam("Sec-WebSocket-Key", pBuffer+i)) { short k = i + 17, ki = 0; while(*(pBuffer + k) != '\r' && *(pBuffer + k) != '\n') { if (*(pBuffer + k) == ':' || *(pBuffer + k) == ' '){ ++k; continue; } else { key[ki++] = *(pBuffer + k); } ++k; } break; } } //MSG_LOG("key:%s...", key); memcpy(key + strlen(key), MAGIC_KEY, sizeof(MAGIC_KEY)); //MSG_LOG("megerkey:%s...", key); //求哈希1 SHA1 sha; unsigned int message_digest[5]; sha.Reset(); sha << key; sha.Result(message_digest); for (int i = 0; i < 5; i++) { message_digest[i] = htonl(message_digest[i]); } memset(key, 0, 512); base64_encode(key, reinterpret_cast(message_digest), 20); char http_res[512] = ""; sprintf(http_res, WEB_SOCKET_HANDS_RE, key); PostUserServerData(pSession, http_res, strlen(http_res), false, false); //MSG_LOG("res:%s...",http_res);//fkYTdNEVkParesYkrM4S pSession->webSocketShakeHand = true; char * pIp = inet_ntoa(pSession->SockAddr.sin_addr); OutputMsg( rmTip, "[%s]握手完毕,nVerifyIdx=%ld",pIp, pSession->nVerifyIdx); } VOID CRunDataProcesser::AddRecvBuf(PRUNGATEUSERSESSION pSession,unsigned long long nVerify, char *pBuffer, int BufferSize) { PCLIENTRECVBUF pRecvBuf; char *pData; if ( pSession->nSocket == INVALID_SOCKET || pSession->boMarkToClose || pSession->boRemoteClosed || !nVerify || pSession->nVerifyIdx != nVerify ) return; //--pSession->boSendAvaliable = true; char * pIp = inet_ntoa(pSession->SockAddr.sin_addr); // 未进行websocket握手,则先握手 if (pSession->webSocketShakeHand) { #ifdef _DEBUG_GATEMSG OutputMsg( rmNormal, ""); OutputMsg( rmTip, "[%s]Idx=%ld: 接收socket数据, 长度为%d, session状态为%d", pIp, pSession->nVerifyIdx, BufferSize, pSession->nSessionSatus); #endif pRecvBuf = (PCLIENTRECVBUF)malloc( sizeof(*pRecvBuf) + BufferSize + 1 ); pRecvBuf->pSession = pSession; pRecvBuf->nVerify = nVerify; pRecvBuf->nBufferSize = BufferSize; pData = (char*)(pRecvBuf + 1); memcpy( pData, pBuffer, BufferSize ); pData[BufferSize] = 0; EnterCriticalSection( &m_RecvQueueLock ); m_pRecvAppendList->add( pRecvBuf ); LeaveCriticalSection( &m_RecvQueueLock ); } else { OutputMsg( rmTip, "[%s]进行握手, 长度为%d, session状态为%d, nVerifyIdx=%ld", pIp, BufferSize, pSession->nSessionSatus, pSession->nVerifyIdx); //OutputMsg( rmTip, "握手数据:\n%s", pBuffer); ShakeHandsHandle(pSession, pBuffer, BufferSize); SendOpenSession(pSession);//发送到LogicServer新增连接 } }