Ejemplo n.º 1
0
int CClientMgr::RegClient(CClient* pClient)
{
	if (NULL == pClient)
	{
		g_pSvrLog->AddRunLog(LL_DEBUG, "CClientMgr::RegClient, wrong pointer");
		return -1;
	}

	int iClientID = pClient->GetRawClientID();
	// 获取的ID不对,返回失败
	if (-1 == iClientID)
	{
		g_pSvrLog->AddRunLog(LL_DEBUG, "CClientMgr::RegClient, Get ClientID Error");
		return -1;
	}
	// 设置该ID
	pClient->SetClientID(iClientID);
	
	// 从未确认队伍删除
	EnterCriticalSection(&m_csRawSection);
	m_oRawClientPtrList.remove(pClient);
	LeaveCriticalSection(&m_csRawSection);
	InterlockedDecrement(&m_lRawClientCount);

	// 加入到已经确认的客户端中来
	EnterCriticalSection(&m_csRegSection);

	// 为了保持客户端ID唯一,必须判断一下,web的ID为0除外
	if (0 != iClientID)
	{
		ClientPtrList::iterator itReg = m_oRegClientPtrList.begin();
		ClientPtrList::iterator itRegEnd = m_oRegClientPtrList.end();
		
		for (; itReg != itRegEnd;)
		{
			if ((*itReg)->GetClientID() == pClient->GetClientID())
			{
				InsertPendingAccept(*itReg);
				itReg = m_oRegClientPtrList.erase(itReg);
				InterlockedDecrement(&m_lRegClientCount);
				break;
			}
			else
			{
				itReg++;
			}
		}
	}
	m_oRegClientPtrList.push_back(pClient);
	LeaveCriticalSection(&m_csRegSection);
	InterlockedIncrement(&m_lRegClientCount);
	return m_lRegClientCount;
}
int MightyTCPCompletionPortServer::acceptSocketObject()
{
	int i=0;
	for(i=0; i<5; i++)
	{
		PCompletionPort_BufObj pUseBuf=AllocateBuffer(m_pListenObj,4096);
		InsertPendingAccept(pUseBuf);
		PostAccept(pUseBuf);
	}
	// 构建事件对象数组,以便在上面调用WSAWaitForMultipleEvents函数
	HANDLE hWaitEvents[2 + MAX_THREAD];
	int nEventCount = 0;
	hWaitEvents[nEventCount ++] =m_hAcceptEvent;
	hWaitEvents[nEventCount ++] =m_hRepostEvent;

	// 创建指定数量的工作线程在完成端口上处理I/O
	for(i=0; i<MAX_THREAD; i++)
	{
		HandleIOCompletionPortServer * pIOThread=new HandleIOCompletionPortServer();
		pIOThread->start(this);
		pIOThread->setExecuteSignal();
		m_tdPoolIndex++;
		hWaitEvents[nEventCount ++] =pIOThread->GetThreadHandle();
	}

	// 下面进入无限循环,处理事件对象数组中的事件
	while(TRUE)
	{
		int nIndex = ::WSAWaitForMultipleEvents(nEventCount, hWaitEvents, FALSE, 60*1000, FALSE);

		// 首先检查是否要停止服务
		if((m_exitNotify==1) || (nIndex == WSA_WAIT_FAILED))
		{
			// 关闭所有连接
			//CloseAllConnections();
			::Sleep(0);		// 给I/O工作线程一个执行的机会
			// 关闭监听套节字
			::closesocket(m_ListenSock);
			m_ListenSock= INVALID_SOCKET;
			::Sleep(0);		// 给I/O工作线程一个执行的机会

			// 通知所有I/O处理线程退出
			for(int i=2; i<MAX_THREAD + 2; i++)
			{	
				::PostQueuedCompletionStatus(m_hCompletionPort, -1, 0, NULL);
			}

			// 等待I/O处理线程退出
			/*::WaitForMultipleObjects(MAX_THREAD, &hWaitEvents[2], TRUE, 5*1000);

			for(i=2; i<MAX_THREAD + 2; i++)
			{	
				::CloseHandle(hWaitEvents[i]);
			}*/
			unsigned long leftIndex,RightIndex;
			RightIndex=m_pThreadPool.size();
			for (leftIndex=0;leftIndex<RightIndex;leftIndex++)
			{
				delete ((HandleIOCompletionPortServer *)m_pThreadPool[leftIndex]);
				Sleep(10);
			}
				

			::CloseHandle(m_hCompletionPort);


			::ExitThread(0);
		}	

		//定时检查所有未返回的AcceptEx I/O的连接建立了多长时间
		if(nIndex == WSA_WAIT_TIMEOUT)
		{
			CheckPostAcceptTimeOut();
		}
		else
		{
			nIndex = nIndex - WAIT_OBJECT_0;
			WSANETWORKEVENTS ne;
			int nLimit=0;
			if(nIndex == 0)
			{
				::WSAEnumNetworkEvents(m_ListenSock,hWaitEvents[nIndex], &ne);
				if(ne.lNetworkEvents & FD_ACCEPT)
				{
					nLimit = 50;  // 增加的个数,这里设为50个
				}
			}
			else if(nIndex == 1)
			{
				nLimit = InterlockedExchange(&m_nRepostCount, 0);
			}
			else if(nIndex > 1)		// I/O服务线程退出,说明有错误发生,关闭服务器
			{
				m_exitNotify=1;
				continue;
			}

			// 投递nLimit个AcceptEx I/O请求
			int i = 0;
			while(i++<nLimit)
			{
				PCompletionPort_BufObj pBeforeHandBuf=AllocateBuffer(m_pListenObj,4096);
				if (pBeforeHandBuf!=NULL)
				{
					InsertPendingAccept(pBeforeHandBuf);
					PostAccept(pBeforeHandBuf);
				}

			}
		}
	}
	return 0;
}
Ejemplo n.º 3
0
void CClientMgr::PollPendingAccept(int& iReturnCode)
{
	CClient *pClient = NULL;

    EnterCriticalSection(&m_csPendingSection);

	ClientPtrList::iterator it = m_oPendingAcceptClientList.begin();
    ClientPtrList::iterator itEnd = m_oPendingAcceptClientList.end();

	for (; it != itEnd; it++)
	{
		pClient = *(it);

		int iOptval = 0;
		int iOptlen = 0;
		iOptlen = sizeof(iOptval);
		
		iReturnCode = getsockopt(
			pClient->m_skClient,
			SOL_SOCKET,
			SO_CONNECT_TIME,
			(char *)&iOptval,
			&iOptlen
			);
		
		if (iReturnCode == SOCKET_ERROR)
		{
			//g_pSvrLog->AddRunLog(LL_DEBUG, "getsockopt: SO_CONNECT_TIME failed: %d", WSAGetLastError());
			pClient->ClearAllData();
			continue;
		}
		else
		{
			// If the socket has been connected for more than 6 minutes,
			//    close it. If closed, the AcceptEx call will fail in the
			//    completion thread.
			if ((iOptval != 0xFFFFFFFF) && (iOptval > 360))
			{
				//g_pSvrLog->AddRunLog(LL_DEBUG, "closing stale handle");
				pClient->ClearAllData();
			}
		}
		
	}
	LeaveCriticalSection(&m_csPendingSection);

	EnterCriticalSection(&m_csRawSection);
    ClientPtrList::iterator itRaw = m_oRawClientPtrList.begin();
	ClientPtrList::iterator itRawEnd = m_oRawClientPtrList.end();
	for (; itRaw != itRawEnd; )
	{
		pClient = *(itRaw);
		
		int iOptval = 0;
		int iOptlen = 0;
		iOptlen = sizeof(iOptval);
		
		iReturnCode = getsockopt(
			pClient->m_skClient,
			SOL_SOCKET,
			SO_CONNECT_TIME,
			(char *)&iOptval,
			&iOptlen
			);
		
		if (iReturnCode == SOCKET_ERROR)
		{
			g_pSvrLog->AddRunLog(LL_DEBUG, "getsockopt: SO_CONNECT_TIME failed: %d", WSAGetLastError());
			itRaw = m_oRawClientPtrList.erase(itRaw);
			InterlockedDecrement(&m_lRawClientCount);
			InsertPendingAccept(pClient);

			continue;
		}
		else
		{
			// If the socket has been connected for more than 5 minutes,
			//    close it. If closed, the AcceptEx call will fail in the
			//    completion thread.
			if ((iOptval != 0xFFFFFFFF) && (iOptval > 300))
			{
				//g_pSvrLog->AddRunLog(LL_DEBUG, "closing stale handle");
				itRaw = m_oRawClientPtrList.erase(itRaw);
				InterlockedDecrement(&m_lRawClientCount);
                InsertPendingAccept(pClient);
			}
			else
			{
				itRaw++;
			}
		}
	}

	LeaveCriticalSection(&m_csRawSection);
}