INT32 CNetChannel::InitNetChannel(CBufferArray* pBufferArray) { INT32 iMsgSize; INT32 iRet = 0; iMsgSize = GetMaxMsgSize(); if(NULL == m_pRecvBuf) { m_pRecvBuf = (char*)malloc(iMsgSize * 2); if(NULL == m_pRecvBuf) { LOG2_FATAL( "Malloc %d fail.\n", iMsgSize * 2); return -1; } memset(m_pRecvBuf, 0, iMsgSize * 2); } if(NULL == m_pRecvPackBuf) { m_pRecvPackBuf = (char*)malloc(iMsgSize * 2); if(NULL == m_pRecvPackBuf) { LOG2_FATAL("Malloc %d fail.\n", iMsgSize * 2); return -1; } memset(m_pRecvPackBuf, 0, iMsgSize * 2); m_iRecvPackBufSize = iMsgSize * 2; } if(NULL == m_pSendPackBuf) { m_pSendPackBuf = (char*)malloc(iMsgSize * 2); if(NULL == m_pSendPackBuf) { LOG2_FATAL("Malloc %d fail.\n", iMsgSize * 2); return -1; } memset(m_pSendPackBuf, 0, iMsgSize * 2); m_iSendPackBufSize = iMsgSize * 2; } m_pBufferArray = pBufferArray; iRet = m_MgrSendBuffer.InitBufferMgr(pBufferArray); if(iRet < 0) { LOG2_ERROR( "m_MgrSendBuffer.InitBufferMgr fail.\n"); return -1; } iRet = m_MgrRecvBuffer.InitBufferMgr(pBufferArray); return iRet; }
INT32 CBufMgr::PushBuffer(CBufferObj *pBufObj) { CBufferObj** pArray; CBufferObj* pBufPos; INT32 iExtBufSize = 0; INT32 i; if(NULL == pBufObj || NULL == m_pBufferArray) { LOG2_ERROR("Args invalid.\n"); return -1; } pBufPos = m_pBufferArray[m_iWritePos]; if(NULL != pBufPos) // 需要重新分配 { m_MutexRelloc.Lock(); iExtBufSize = m_iBufferArraySize; pArray = new CBufferObj*[m_iBufferArraySize + DEFAULT_LOCAL_BUFFER_ARRAY_SIZE]; if(NULL == pArray) { LOG2_FATAL("New object ptr size:%d fail.\n", m_iBufferArraySize + DEFAULT_LOCAL_BUFFER_ARRAY_SIZE); m_MutexRelloc.Unlock(); return -2; } m_iBufferArraySize += DEFAULT_LOCAL_BUFFER_ARRAY_SIZE; memset(pArray, 0, sizeof(CBufferObj*) * m_iBufferArraySize); for(i = 0; i < iExtBufSize; i++) { pArray[i] = m_pBufferArray[(m_iReadPos + i) % iExtBufSize]; } delete m_pBufferArray; m_pBufferArray = pArray; m_iReadPos = 0; m_iWritePos = iExtBufSize; m_MutexRelloc.Unlock(); } m_pBufferArray[m_iWritePos] = pBufObj; m_iWritePos++; if(m_iWritePos >= m_iBufferArraySize) { m_iWritePos = 0; } return 0; }
/* ------------------------------------------------------------------------- */ static int OnMessageReceived(TServant *const servant, ezxml_t message) { int ret = -EXIT_SUCCESS; #ifdef UNIT_TESTS if (g_Servant_OnMessageReceived) g_Servant_OnMessageReceived(servant, message); #endif assert(message); do { const char *req; const char *error; error = ezxml_error(message); if ('\0' != error[0]) { LOG2_ERROR("servant", "the session (%u) received an invalid " "formated xml message: %s", servant->m_session.m_id, error); ret = -EXIT_FAILURE; break; } req = ezxml_name(message); LOG2_DEBUG("servant", "the session (%u) received '%s' request", servant->m_session.m_id, req); if (strcmp(req, "update") == 0) { if (servant->m_reg) { if ((ret = Reg_Update(servant->m_reg, message))) LOG2_ERROR("servant", "the session (%u) failed to update " "the registry", servant->m_session.m_id, req); } } else if (strcmp(req, "retrieve") == 0) { if (servant->m_reg) { ezxml_t status = ezxml_new("status"); ret = Reg_Get(servant->m_reg, message, status); TxMessage(servant, status); ezxml_free(status); LOG2_DEBUG("servant", "the session (%u) replied to '%s' request", servant->m_session.m_id, req); } } else { LOG2_WARNING("servant", "the session (%u) received an undefined " "request (%s)", servant->m_session.m_id, req); ret = -EXIT_FAILURE; } } while(0); ezxml_free(message); return ret; }
INT32 CNetChannel::OnCheckStatus() { INT32 iNetDataTimeout; INT32 iRet; fnNetEvent OnNetEventCB; if(NET_CHANNEL_STATUS_INVALID == m_iNetChnStatus) { return 0; } SendPulse(); //长期收不到网络包 m_iNetRecvDataCount++; iNetDataTimeout = GetNetDataTimeout(); if(m_iNetChnStatus != NET_CHANNEL_STATUS_ACTIVE) { LOG2_DEBUG( "ChnType(%d) %s:%d => %s:%d. Set timeout.\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort()); m_iNetRecvDataCount = iNetDataTimeout + 1; } if( m_iNetRecvDataCount == iNetDataTimeout || (m_bSendDisconnectEvent && m_iNetChnStatus != NET_CHANNEL_STATUS_ACTIVE) ) { LOG2_DEBUG( "ChnType(%d) %s:%d => %s:%d. Keeplavie timeout %d>=%d. IsDisCnn:%d\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort(), m_iNetRecvDataCount,iNetDataTimeout, m_bSendDisconnectEvent ); m_iNetRecvDataCount = 0; m_bSendDisconnectEvent = 0; OnNetEventCB = GetNetEventEntry(); if(NULL != OnNetEventCB) { SetChnStatus(NET_CHANNEL_STATUS_SHUTDOWN); OnNetEventCB(GetNetEventCaller(), this, NET_EVENT_CLOSE, NULL); } return 0; } if( m_iNetRecvDataCount > iNetDataTimeout) { m_iNetRecvDataCount = iNetDataTimeout; } if(NET_CHANNEL_TYPE_CLIENT == GetChnType()) { INT32 iPulseTime = GetNetPulseTime(); //客户端需要主动发送心跳包,掉线需要重连 if( m_iNetChnStatus == NET_CHANNEL_STATUS_ACTIVE ) { m_iSendPulseCount++; } if( m_iSendPulseCount * 1250 >= iPulseTime ) { //发送心跳 // m_MutexSend.Lock(); // SendRemoteData(NULL, 0); // m_MutexSend.Unlock(); m_bSendPulse = 1; m_iSendPulseCount = 0; } //重连操作 INT32 iReConnect = GetSupportReConnect(); INT32 iNetStat = GetChnStatus(); if( !m_bSendDisconnectEvent && (NET_CHANNEL_STATUS_NO_CONNECT == iNetStat || NET_CHANNEL_STATUS_SOCKET_ERROR == iNetStat || NET_CHANNEL_STATUS_SHUTDOWN == iNetStat) ) { if(SUPPORT_RECONNECT == iReConnect) { m_iReConnectCount++; if(m_iReConnectCount * 1000 >= GetReConnectTime()) { LOG2_ERROR( "ChnType(%d) %s:%d => %s:%d. Reconnect status:%d On: %ld.\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort(), iNetStat, (long)time(NULL) ); m_iReConnectCount = 0; INT32 iReuse = GetReuseNetPortFlag(); if (iReuse == REUSE_NETPORT_FLAG) { iRet = ConnectServer(GetRemoteIPAddrString(), GetRemotePort(), GetLocalIPAddrString(), GetLocalPort()); } else { iRet = ConnectServer(GetRemoteIPAddrString(), GetRemotePort(), "", 0); } if(0 == iRet) { LOG2_ERROR( "Connect %s:%d bind: %s:%d fail.\n", GetRemoteIPAddrString(), GetRemotePort(), GetLocalIPAddrString(), GetLocalPort() ); m_iNetRecvDataCount = 0; OnNetEventCB = GetNetEventEntry(); if(NULL != OnNetEventCB) { OnNetEventCB(GetNetEventCaller(), this, NET_EVENT_CONNECT, NULL); } } } } } } return 0; }
INT32 CNetChannel::SendRemoteMsg(UINT32 uiCMDID, void* pMSG, INT32 iMSGLen, StruID* pSrcID, StruID* pDstID, UINT16 uiSessionID) { INT32 iRet; INT32 iTotalDataLen; m_MutexSend.Lock(); if( m_iNetChnStatus != NET_CHANNEL_STATUS_ACTIVE ) { m_MutexSend.Unlock(); return -64; } iTotalDataLen = iMSGLen + sizeof(StruUserProtocolHead); if(iTotalDataLen > m_iSendPackBufSize) //需要重新分配发送缓冲区大小 { m_pExtSendPackBuf = (char*)malloc(iTotalDataLen); if(NULL == m_pExtSendPackBuf) { m_MutexSend.Unlock(); return -1; } memset(m_pExtSendPackBuf, 0, iTotalDataLen); } else { m_pExtSendPackBuf = m_pSendPackBuf; } iRet = PacketUserMsg(uiCMDID, pMSG, iMSGLen, pSrcID, pDstID, uiSessionID, m_pExtSendPackBuf); if(iRet < 0) { LOG2_ERROR("ChnType(%d) %s:%d => %s:%d PacketUserMsg fail, Ret:%d\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort(), iRet); m_MutexSend.Unlock(); return -2; } iRet = SendRemoteData(m_pExtSendPackBuf, iTotalDataLen); if(iTotalDataLen > m_iSendPackBufSize) { free(m_pExtSendPackBuf); } if( iRet < 0 ) { LOG2_ERROR("ChnType(%d) %s:%d => %s:%d SendRemoteData %d fail, Ret:%d\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort(),iTotalDataLen, iRet); } m_pExtSendPackBuf = NULL; m_MutexSend.Unlock(); return iRet; }
/*************************************************************************** Function: SendRemoteData DATE: 2010-8-5 20:59 Description: 向远端发送数据 Input: pData:发送数据地址 iDataLen:发送数据长度 Output: Return: 发送字节数 Note: ****************************************************************************/ INT32 CNetChannel::SendRemoteData(char* pData, INT32 iDataLen) { INT32 iPacketLen = 0; INT32 iRet; INT32 iBufSize; INT32 iSendPos = 0; INT32 iTotal = 0; INT32 iCur = 0; char* pDstBuf; CBufferObj* pFreeBuf; INT32 i; INT32 iSendLen; INT32 iResLen = 0; INT32 iSessionID; CBufferObj* pObjBuf; if(NULL == m_pSocketChn) { LOG2_ERROR("m_pSocketChn is null\n"); return -1; } if(NULL == m_pBufferArray) { LOG2_ERROR("m_pBufferArray is null\n"); return -2; } if(iDataLen > 0) { m_iSessionID++; if(0 == m_iSessionID) { m_iSessionID = 1; } iSessionID = m_iSessionID; } else { iSessionID = 0; } //每个包的大小 iBufSize = m_pBufferArray->GetBuferSize(); if(iBufSize > GetMaxMsgSize()) { iBufSize = GetMaxMsgSize(); } iTotal = iDataLen / (iBufSize - sizeof(StruCommuHeader)); if(0 == iDataLen) { iTotal = 1; } else if(iDataLen % (iBufSize - sizeof(StruCommuHeader))) { iTotal++; } iResLen = iDataLen; for(i = 0; i < iTotal; i++) { pFreeBuf = m_pBufferArray->GetFreeBuffer(); if(NULL == pFreeBuf) { LOG2_ERROR("GetFreeBuffer fail. i:%d\n", i ); return -3; } pDstBuf = pFreeBuf->GetData(); if(NULL == pDstBuf) { LOG2_ERROR("GetData fail. i:%d\n", i ); return -4; } iCur++; if(iResLen < (INT32)(iBufSize - sizeof(StruCommuHeader))) { iSendLen = iResLen; } else { iSendLen = iBufSize - sizeof(StruCommuHeader); } PackData(pData + iSendPos, iSendLen, pDstBuf, &iPacketLen, iSessionID, iTotal, iCur); iSendPos += iSendLen; iResLen -= iSendLen; pFreeBuf->SetDataSize(iPacketLen); m_MgrSendBuffer.PushBuffer(pFreeBuf); } while(TRUE) { pObjBuf = m_MgrSendBuffer.PopBuffer(); if(NULL == pObjBuf) { break; } int iLen = pObjBuf->GetDataSize(); iRet = m_pSocketChn->SendData(pObjBuf->GetData(), iLen); m_pBufferArray->FreeBuffer(pObjBuf); if(iRet != ERROR_BASE_SUCCESS ) { LOG2_ERROR("ChnType(%d) Socket: %s:%d => %s:%d SendData fail, Ret:%d\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort(), iRet); m_bSendDisconnectEvent = 1; SetChnStatus(NET_CHANNEL_STATUS_SOCKET_ERROR); //禁止再发送 return -5; } } return 0; }
INT32 CNetChannel::ConnectServer(char* pszRemoteIPAddr, UINT16 uiRemotePort, char* pszBindingIPAddr, UINT16 uiBindingPort) { INT32 iRet; enumNetProtocolType euPType; LOG2_INFO("ChnType(%d) Connect %s:%d bind:%s:%d", GetChnType(), pszRemoteIPAddr, uiRemotePort, pszBindingIPAddr ? pszBindingIPAddr : "0" , uiRemotePort ); if(m_pSocketChn) { LOG2_DEBUG("ChnType(%d) Close Socket: %s:%d => %s:%d .\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort()); m_MutexSend.Lock(); ISocketChannel *pSocket = m_pSocketChn; m_pSocketChn = NULL; m_MutexSend.Unlock(); if( pSocket ) { pSocket->CloseChannelEx(); } } if(NULL == m_pSocketChn) { if(m_pNetService) { if(GetProtocolType() == PROTOCOL_TYPE_TCP) { euPType = NET_PROTOCOL_TCP; } else { euPType = NET_PROTOCOL_UDP; } ISocketChannel *pSocket = NULL; iRet = m_pNetService->AddClientChannel(m_szRemoteIPAddr, uiRemotePort, pszBindingIPAddr, uiBindingPort, euPType, &pSocket); if(iRet < 0 || NULL == pSocket) { LOG2_ERROR("ChnType(%d) Connect %s:%d bind:%s:%d protype:%d fail.", GetChnType(), pszRemoteIPAddr, uiRemotePort, pszBindingIPAddr ? pszBindingIPAddr : "0" , uiRemotePort,(int) euPType ); return -1; } SetSocketChn( pSocket, NET_CHANNEL_STATUS_ACTIVE ); LOG2_DEBUG("ChnType(%d) Connect Socket: %s:%d => %s:%d OK.\n", GetChnType(), GetLocalIPAddrString(),GetLocalPort(), GetRemoteIPAddrString(),GetRemotePort()); } else { CMM_ASSERT(0); return -1; } } else { iRet = m_pSocketChn->ReConnect(); } return iRet; }