Bool HawkGateThread::StartSession(SOCKET hSocket, const SocketAddr& sAddr) { //套接字有效 if (hSocket == INVALID_SOCKET) return false; //创建缓存事件 bufferevent* pEvent = bufferevent_socket_new((event_base*)m_pBase, hSocket, BEV_OPT_CLOSE_ON_FREE); if (!pEvent) return false; //创建会话 Session* pSession = AllocSession(hSocket, sAddr); if (!pSession) { bufferevent_free(pEvent); return false; } pSession->Event = pEvent; //设置回调 bufferevent_setcb(pEvent, hawk_GateSessionRead, hawk_GateSessionWrite, hawk_GateSessionError, pSession); //设置读超时, 可做为心跳机制 Int32 iTimeout = m_pGateway->GetSessionTimeout(); if (iTimeout > 0) { struct timeval tv; tv.tv_sec = iTimeout / 1000; tv.tv_usec = (iTimeout % 1000) * 1000; bufferevent_set_timeouts(pEvent, &tv, NULL); } //开启读写事件 bufferevent_enable(pEvent, EV_READ | EV_WRITE); //添加到会话列表 m_mSession[pSession->Sid] = pSession; //调用性能监视器 if (m_pGateway->GetProfiler()) m_pGateway->GetProfiler()->RegConnect(true); //添加日志 HawkFmtLog("SessionStart, Sid: %u, Address: %s", pSession->Sid, pSession->Addr->ToString().c_str()); return true; }
int LSelectServer::CheckForSocketEvent() { if (!m_SelectServerSessionManager.BuildSet()) { return -1; } fd_set rdset = m_SelectServerSessionManager.GetRecvSet(); fd_set wrset = m_SelectServerSessionManager.GetSendSet(); map<int, LSelectServerSession*>* pMapSocket = m_SelectServerSessionManager.GetSessionManagerForEvent(); struct timeval val; val.tv_sec = 0; val.tv_usec = 0; int iReturn = select(m_SelectServerSessionManager.GetMaxSocketPlus1(), &rdset, &wrset, NULL, &val); if (iReturn == -1) { return -1; } else if (iReturn == 0) { return 0; } int nListenSocket = GetSocket(); if (FD_ISSET(nListenSocket, &rdset)) { int nAcceptedSocket = accept(nListenSocket, NULL, NULL); if (nAcceptedSocket != -1) { LSelectServerSession* pSession = AllocSession(); if (pSession == NULL) { #ifndef WIN32 close(nAcceptedSocket); #else closesocket(nAcceptedSocket); #endif } else { pSession->SetSocket(nAcceptedSocket); if (!AddSession(pSession)) { #ifndef WIN32 close(nAcceptedSocket); #else closesocket(nAcceptedSocket); #endif FreeSession(pSession); } else { AddOneRecvedPacket(pSession->GetSessionID(), (LPacketSingle*)0xFFFFFFFF); } } } } map<int, LSelectServerSession*>::iterator _ito = pMapSocket->begin(); while (_ito != pMapSocket->end()) { int nTempSocket = _ito->first; LSelectServerSession* pSelectServerSession = _ito->second; if (pSelectServerSession == NULL) { _ito++; continue; } if (FD_ISSET(nTempSocket, &rdset)) { int nErrorID = pSelectServerSession->SessionRecv(); if (nErrorID < 0) { pSelectServerSession->SetSendable(false); AddOneCloseSessionWork(pSelectServerSession->GetSessionID()); _ito++; continue; } } if (FD_ISSET(nTempSocket, &wrset)) { pSelectServerSession->SetSendable(true); } _ito++; } return 1; }
int LSelectServer::ThreadDoing(void* pParam) { while (1) { unsigned short usProcessedCloseWorkCount = 0; unsigned int unSessionIDForClose = 0; while (GetOneCloseSessionWork(unSessionIDForClose)) { LSelectServerSession* pSession = FindSession(unSessionIDForClose); if (pSession != NULL) { bool bReconnect = pSession->GetReconnect(); pSession->ReleaseAllPacketInSendQueue(); #ifndef WIN32 close(pSession->GetSocket()); #else closesocket(pSession->GetSocket()); #endif RemoveSession(unSessionIDForClose); FreeSession(pSession); AddOneRecvedPacket(unSessionIDForClose, NULL); if (bReconnect) { char szIP[32]; unsigned short usPort = 0; #ifndef WIN32 pthread_mutex_lock(&m_mutexForConnectToServer); #else EnterCriticalSection(&m_mutexForConnectToServer); #endif if (!m_ConnectorWorkManager.AddConnectWork(szIP, usPort, NULL, 0)) { // error print } #ifndef WIN32 pthread_mutex_unlock(&m_mutexForConnectToServer); #else LeaveCriticalSection(&m_mutexForConnectToServer); #endif } } usProcessedCloseWorkCount++; if (usProcessedCloseWorkCount >= 200) { break; } } t_Connector_Work_Result cwr; memset(&cwr, 0, sizeof(cwr)); int nProcessConnecttedWorkCount = 0; while (GetOneConnectedSession(cwr)) { LSelectServerSession* pSession = AllocSession(); if (pSession == NULL) { #ifndef WIN32 close(cwr.nSocket); pthread_mutex_lock(&m_mutexForConnectToServer); #else closesocket(cwr.nSocket); EnterCriticalSection(&m_mutexForConnectToServer); #endif if (!m_ConnectorWorkManager.AddConnectWork(cwr.szIP, cwr.usPort, NULL, 0)) { // error print } #ifndef WIN32 pthread_mutex_unlock(&m_mutexForConnectToServer); #else LeaveCriticalSection(&m_mutexForConnectToServer); #endif nProcessConnecttedWorkCount++; if (nProcessConnecttedWorkCount >= 200) { break; } continue; } else { pSession->SetSocket(cwr.nSocket); if (!AddSession(pSession)) { #ifndef WIN32 close(cwr.nSocket); pthread_mutex_lock(&m_mutexForConnectToServer); #else closesocket(cwr.nSocket); EnterCriticalSection(&m_mutexForConnectToServer); #endif if (!m_ConnectorWorkManager.AddConnectWork(cwr.szIP, cwr.usPort, NULL, 0)) { // error print } #ifndef WIN32 pthread_mutex_unlock(&m_mutexForConnectToServer); #else LeaveCriticalSection(&m_mutexForConnectToServer); #endif FreeSession(pSession); } else { pSession->SetReconnect(true); AddOneRecvedPacket(pSession->GetSessionID(), (LPacketSingle*)0xFFFFFFFF); } } nProcessConnecttedWorkCount++; if (nProcessConnecttedWorkCount >= 200) { break; } } int nWorkCount = CheckForSocketEvent(); if (nWorkCount < 0) { return 0; } int nSendWorkCount = SendData(); if (nWorkCount == 0 && nSendWorkCount == 0) { // sched_yield(); #ifndef WIN32 struct timespec timeReq; timeReq.tv_sec = 0; timeReq.tv_nsec = 10; nanosleep(&timeReq, NULL); #else Sleep(0); #endif } if (CheckForStop()) { return 0; } } return 0; }