#include "stdafx.h" #include //#include "Client2SrvType.h" #include "Global.h" #include "TwoShipperSocket.h" #include "crc32.h" #pragma warning(push) #pragma warning(disable:4995) #pragma warning(pop) //---------------------------------------------- CTwoShipperSocket ---- CTwoShipperSocket::CTwoShipperSocket() { m_bIsServer = false; m_hHeartHandle = NULL; m_bHeartExit = false; m_bClientLoginServerSuccess = false; m_dwServiceOnlineTick = 0; CString sTemp; DllC_GetAddressInfo( sTemp,m_sLocalGateway ); } CTwoShipperSocket::CTwoShipperSocket(int nIsInSlave) { m_bIsServer = nIsInSlave; m_hHeartHandle = NULL; m_bHeartExit = false; m_bClientLoginServerSuccess = false; m_dwServiceOnlineTick = 0; } CTwoShipperSocket::~CTwoShipperSocket() { if( m_hHeartHandle ) { m_bHeartExit = true; delete m_hHeartHandle; m_hHeartHandle = NULL; } //DllC_LogoutServer(); } /////////////////////////////////////////////////////////////////////////////// // 实现ISocketClientHandler的通信方法 void CTwoShipperSocket::DllS_ThreadBegin(CString sServerIP) { CString show; show.Format("#%s开始线程",sServerIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllS_ThreadExit(CString sServerIP) { CString show; show.Format("#%s离开线程",sServerIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllS_DataReceived(CString sServerIP,const BYTE* pbData, DWORD dwCount, CString sClientIP) { //LOG4C_HEX_DUMP( (LOG_INFO,(const char *)pbData,dwCount)); //if( !m_SocketClient->IsOpen() ) return; //ProcessData( pSH, pbData, dwCount ); CString show; show.Format("#%s接收到%s的数据",sServerIP,sClientIP ); LOG4C((LOG_INFO, show)); OnCmdProcess( (void *)pbData ); } void CTwoShipperSocket::DllS_ConnectionDropped(CString sServerIP,CString sClientIP) { CString show; show.Format("#客户端%s掉线",sClientIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllS_ConnectionError(CString sServerIP,DWORD dwError) { CString show; show.Format("#连接%s失败,错误码为%d",sServerIP,dwError ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllS_ConnectionFailure(CString sServerIP,CString sClientIP) { CString show; show.Format("#%s连接%s失败",sClientIP,sServerIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllS_AddConnection(CString sServerIP,CString sClientIP) { m_sClientIP = sClientIP; CString show; show.Format("#%s增加新的连接%s",sServerIP,sClientIP ); LOG4C((LOG_INFO, show)); if( m_bIsServer && m_hHeartHandle == NULL ) { LOG4C_FUN( ("Server Creat CheckHeartProc" )); m_dwServiceOnlineTick = GetTickCount(); m_hHeartHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckHeartProc, this, 0, 0); m_bHeartExit = false; } } void CTwoShipperSocket::DllC_ThreadBegin(CString sLocalIP) { //InitializeCriticalSection(&pSH->m_hClient2SrvSection); if( !m_bIsServer && m_hHeartHandle == NULL ) { LOG4C_FUN( ("Client Creat SendHeartProc" )); m_hHeartHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendHeartProc, this, 0, 0); m_bHeartExit = false; } CString show; show.Format("#%s开始线程",sLocalIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllC_ThreadExit(CString sLocalIP) { CString show; show.Format("#%s退出线程",sLocalIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllC_DataReceived( CString sLocalIP,const BYTE* pbData, DWORD dwCount, CString sServerIP) { CString show; show.Format("#收到%s的数据",sServerIP ); LOG4C((LOG_INFO, show)); } void CTwoShipperSocket::DllC_ConnectionDropped(CString sLocalIP, CString sServerIP) { CString show; show.Format("#%s掉线",sServerIP ); LOG4C((LOG_INFO, show)); m_bClientLoginServerSuccess = false; } void CTwoShipperSocket::DllC_ConnectionError( CString sLocalIP,DWORD dwError) { CString show; show.Format("#%s连接错误,错误码为%d",sLocalIP,dwError ); LOG4C((LOG_INFO, show)); } unsigned int CTwoShipperSocket::CalcCheckSum( void *pData, unsigned int nSize ) { unsigned int checksum = 0; if ( nSize < sizeof( ProtocolHeader ) ) { return 0; } unsigned char *pBody = &( ( unsigned char* )pData )[ sizeof( ProtocolHeader ) ]; nSize -= sizeof( ProtocolHeader ); checksum = crc32( 0, pBody, nSize ); return checksum; } void CTwoShipperSocket::ProcessHeart(void *pData, int nLen) { //m_SocketClient->Write((const LPBYTE)pData, nLen, NULL); //ProtocolHeader *pHeader = (ProtocolHeader *)pData; //if( pHeader != NULL ) //{ // if( pHeader->nCmdType >= 0 && pHeader->nCmdType < MAX_DllS__TYPE ) // { // g_dwServiceOnlineTick[pHeader->nCmdType] = GetTickCount(); // //CString str; // //str.Format("动态库类型=%d, 收到心跳包", pHeader->nCmdType); // //LogEvent(str); // } //} //LogEvent("收到心跳包"); } int CTwoShipperSocket::OnCmdProcess(void *pData) { ProtocolHeader *pHeader = (ProtocolHeader *)pData; if( pHeader == NULL ) return -1; if( pHeader->nLen < 0 || pHeader->nLen > 65535 ) return -1; switch( pHeader->nCmd ) { case CMD_TWOSHIPPER_HEART: { //LOG4C_FUN(( "*********心跳包**********")); m_dwServiceOnlineTick = GetTickCount(); } break; } return 0; } void CTwoShipperSocket::ProcessData(CSocketHandle *pSH, const BYTE* pData, DWORD nLen) { DWORD nBuffIndex = 0; EnterCriticalSection( &(pSH->m_hClient2SrvSection) ); while( nBuffIndex < nLen ) { ProtocolHeader *pHeader; //当前协议包头 DWORD nProcessedLen = 0; //当前循环处理了多少个字节 if( pSH->m_nPendingSize > 0 ) // 开始组包 { pHeader = (ProtocolHeader *)pSH->m_PendingBuffer; if( pSH->m_nPendingSize < sizeof(ProtocolHeader) ) //上一次接收到的长度小于包头 { DWORD nLinkHeaderLen = sizeof( ProtocolHeader ) - pSH->m_nPendingSize; if( nLinkHeaderLen <= nLen ) //这次可以收完包头 { memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLinkHeaderLen ); //这里已经收完Header nProcessedLen = pHeader->nLen - pSH->m_nPendingSize; if( nProcessedLen <= nLen ) //如果所需处理的长度小于等于当前包长度 { memcpy( &pSH->m_PendingBuffer[ sizeof( ProtocolHeader ) ], & ( ( char *) pData )[ nLinkHeaderLen ], pHeader->nLen - sizeof( ProtocolHeader ) ); pSH->m_nPendingSize = 0; // 收完所需的包,置m_nPendingSize为0 } else { int nTemp = nLen - nLinkHeaderLen; //除去头剩余部分的长度 if ( nTemp > 0 ) //刚好是Header的长度,不用拷贝内存,所以这里加了>0的判断 { memcpy( &pSH->m_PendingBuffer[ sizeof( ProtocolHeader ) ], & ( ( char *) pData )[ nLinkHeaderLen ], nTemp ); } pSH->m_nPendingSize += nLen; } } else //这次还是没有收完包头, 继续Pending { memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLen ); pSH->m_nPendingSize += nLen; nProcessedLen = nLen; } } else //Header部分已经在阻塞的缓冲区中 { nProcessedLen = pHeader->nLen - pSH->m_nPendingSize; if ( nProcessedLen <= nLen ) //如果需要处理的长度小于现有包的长度 { memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nProcessedLen ); pSH->m_nPendingSize = 0; } else //否则要继续阻塞 { memcpy( &pSH->m_PendingBuffer[ pSH->m_nPendingSize ], pData, nLen ); pSH->m_nPendingSize += nLen; } } } else //第一次接包 { pHeader = (ProtocolHeader *)&( (unsigned char *)pData )[nBuffIndex]; if( nLen - nBuffIndex < sizeof(ProtocolHeader) ) // 没有收够包头,先记录当前收到的Buffer { //如果第一次接包就没有收够包头,认为是非法包,扔掉,就是说已处理的长度nProcessedLen = 0 pSH->m_nPendingSize = nLen - nBuffIndex; memcpy(pSH->m_PendingBuffer, pHeader, pSH->m_nPendingSize); } else { nProcessedLen = pHeader->nLen; if( (int)pHeader->nLen > nLen - nBuffIndex ) { memcpy(pSH->m_PendingBuffer, pHeader, nLen - nBuffIndex); //如果第一次接包,pHeader->nLen大于当前包的总长,认为是非法包,扔掉 if( nBuffIndex == 0 ) { //组包错误,则扔掉当前包 TRACE("pHeader->nLen大于当前包的总长,认为是非法包,扔掉\r\n"); break; } pSH->m_nPendingSize = nLen - nBuffIndex; nProcessedLen = nLen - nBuffIndex; } else { pSH->m_nPendingSize = 0; } } } if ( nProcessedLen == 0 ) { // 没有收够包头,认为是非法包,扔掉 TRACE("没有收够包头,认为是非法包,扔掉\r\n"); break; } if ( pSH->m_nPendingSize == 0 ) { if ( pHeader->nLen > SOCKET_BUFFSIZE ) { // 包长度超过限制 TRACE("pHeader->nLen超过限制\r\n"); } if(-1 == OnCmdProcess( pHeader )) { //MessageBox( NULL, "Error OnCmdProcess", NULL, MB_OK ); TRACE("crc校验错误!\r\n"); break; } } nBuffIndex += nProcessedLen; } LeaveCriticalSection( &(pSH->m_hClient2SrvSection) ); } //客户端调用 DWORD WINAPI CTwoShipperSocket::SendHeartProc( CTwoShipperSocket *pWatchServer ) { while((!pWatchServer->m_bHeartExit )) { ProtocolHeader PH; PH.nLen = 16; PH.nCmd = CMD_TWOSHIPPER_HEART; PH.nCmdType = 0; PH.Verify = pWatchServer->CalcCheckSum( (void *)&PH,16 ); pWatchServer->DllC_SendDateToServer( (BYTE *)&PH,16 ); Sleep(5000); } return 0; } //服务器调用 DWORD WINAPI CTwoShipperSocket::CheckHeartProc( CTwoShipperSocket *pWatchServer ) { while((!pWatchServer->m_bHeartExit )) { if( GetTickCount() - pWatchServer->m_dwServiceOnlineTick > 1 * 60 * 1000 ) //大于两分钟没有心跳包,认为已断线 { if( pWatchServer->DllS_Ping( pWatchServer->m_sLocalGateway ) ) { g_nRunModeForIOServer = 1; LOG4C_FUN( ("Start IOServer" )); } pWatchServer->m_dwServiceOnlineTick = GetTickCount(); } Sleep(5000); } return 0; }