UINT WINAPI CIocpServer::WorkerThreadProc(LPVOID pv)
{
	CIocpServer* pServer	= (CIocpServer*)pv;

	while (TRUE)
	{
		DWORD dwErrorCode = NO_ERROR;

		DWORD dwBytes;
		OVERLAPPED* pOverlapped;
		TSocketObj* pSocketObj;
		TBufferObj* pBufferObj;

		BOOL result = ::GetQueuedCompletionStatus
			(
			pServer->m_hCompletePort,
			&dwBytes,                 //一次完成后的I/O操作所传送数据的字节数
			(PULONG_PTR)&pSocketObj,  //当文件I/O操作完成后,用于存放与之关联的CK socket
			&pOverlapped,             //为调用IOCP机制所引用的OVERLAPPED结构
			INFINITE
			);

		//只有当 接收长度 接收socket 接收缓冲区都为空时才退出
		if((0 == dwBytes) && (NULL == pSocketObj) && (NULL == pOverlapped))
			return 0;

		//用于取得内存中任何结构体的首地址,
		//要提供的参数是:结构体中某个成员(field)的地址address、结构体的类型type、提供地址那个成员的名字field。 
		pBufferObj = CONTAINING_RECORD(pOverlapped, TBufferObj, ov);

		//GetQueuedCompletionStatus失败则返回零值
		if (!result)
		{
			DWORD dwFlag	= 0;
			DWORD dwSysCode = ::GetLastError();

			//判断socket状态  如果还处于启用则继续投递一个接收
			if(pServer->HasStarted())
			{
				SOCKET sock	= pBufferObj->operation != SO_ACCEPT ? pSocketObj->socket : (SOCKET)pSocketObj;
				result		= ::WSAGetOverlappedResult(sock, &pBufferObj->ov, &dwBytes, FALSE, &dwFlag);  //返回指定套接口上一个重叠操作的结果

				//投递失败
				if (!result)
				{
					dwErrorCode = ::WSAGetLastError();
					TRACE3("GetQueuedCompletionStatus failed (SYS: %d, SOCK: %d, FLAG: %d)\n", dwSysCode, dwErrorCode, dwFlag);
				}
			}
			else   
				dwErrorCode		= dwSysCode;   //否则标记失败
		}

		pServer->HandleIo(pSocketObj, pBufferObj, dwBytes, dwErrorCode);
	}

	return 0;
}
Exemple #2
0
// 完成端口的工作线程
unsigned int _stdcall CLCompletionThread(void * lpParam)
{
	SOCKET_OBJ  *sockobj=NULL;	// Per socket object for completed I/O
	BUFFER_OBJ  *bufobj=NULL;	// Per I/O object for completed I/O
	OVERLAPPED  *lpOverlapped=NULL;	// Pointer to overlapped structure for completed I/O
	HANDLE	CompletionPort;		// Completion port handle
	DWORD	BytesTransfered,	// Number of bytes transfered
		Flags;			// Flags for completed I/O
	int	rc, 
		error;

	bool isclient = true;

	CIocpServer * gIocp = (CIocpServer *)lpParam;
	CompletionPort = gIocp->CLCompletionPort;
	ADOConn *pAdo = NULL; 

	if(gIocp->m_bAdo & 2)
	{
		pAdo = new ADOConn();
		pAdo->OpenDatabase(gIocp->m_szAdo);
	}

	while (1)
	{
		error = NO_ERROR;
		lpOverlapped = NULL;
		rc = GetQueuedCompletionStatus(
			CompletionPort,
			&BytesTransfered,
			(PULONG_PTR)&sockobj,
			&lpOverlapped,
			INFINITE
			);

		if(lpOverlapped == NULL)	
		{
#ifdef LOG_LEVEL2
			Log_Server.Write("CLCompletionThread: GetQueuedCompletionStatus failed(lpOverlapped == NULL): %d",GetLastError());
#endif
			continue;
		}
		bufobj = CONTAINING_RECORD(lpOverlapped, BUFFER_OBJ, ol);

		if (rc == FALSE)
		{ //出错时读取错误代码
			rc = WSAGetOverlappedResult(
				sockobj->s,
				&bufobj->ol,
				&BytesTransfered,
				FALSE,
				&Flags
				);
			if (rc == FALSE)
				error = WSAGetLastError();
			
		}

		gIocp->HandleIo(sockobj, bufobj, CompletionPort, BytesTransfered, error,pAdo,isclient);
	}

	if(pAdo)
		delete pAdo;

	_endthreadex(0);
	return 0;
}
UINT WINAPI CIocpServer::AcceptThreadProc(LPVOID pv)
{
	CIocpServer* pServer	= (CIocpServer*)pv;
	pServer->m_psemAccept	= new CSEM(pServer->m_dwAcceptSocketCount, pServer->m_dwAcceptSocketCount);

	ASSERT(pServer->m_soListen		!= INVALID_SOCKET);
	ASSERT(*(pServer->m_psemAccept)	!= NULL);

	TRACE1("---------------> Accept Thread 0x%08X started <---------------\n", ::GetCurrentThreadId());

	while(TRUE)
	{
		HANDLE handles[]	= {*(pServer->m_psemAccept), pServer->m_evtAccept};
		//等候单个对象或所有一系列对象发出信号,或等候指定的超时时间过去(溢出)。如返回条件已经满足,则立即返回
		DWORD dwResult		= ::WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE);
		//第三个参数__in BOOL bWaitAll,如bWaitAll设为TRUE,则下述任何一个常数都标志着成功
		//WAIT_ABANDONED_0:所有对象都发出消息,而且其中有一个或多个属于互斥体(一旦拥有它们的进程中止,就会发出信号)
		//WAIT_TIMEOUT:对象保持未发信号的状态,但规定的等待超时时间已经超过
		//WAIT_OBJECT_0:所有对象都发出信号
		//WAIT_IO_COMPLETION:(仅适用于WaitForMultipleObjectsEx)由于一个I/O完成操作已作好准备执行,所以造成了函数的返回
		//返回WAIT_FAILED则表示函数执行失败,会设置GetLastError
		//
		//如bWaitAll为FALSE,那么返回结果相似,
		// 只是可能还会返回相对于WAIT_ABANDONED_0 或 WAIT_OBJECT_0的一个正偏移量,指出哪个对象是被抛弃还是发出信号。
		// 例如,WAIT_OBJECT_0 + 5的返回结果意味着列表中的第5个对象发出了信号
		

		
		/*
		if(dwResult == WAIT_OBJECT_0)
		{
		DWORD dwResult2 = ::WaitForSingleObjectEx(pServer->m_evtAccept, 0L, FALSE);

		if(dwResult2 == WAIT_OBJECT_0)
		dwResult = WAIT_OBJECT_0 + 1;
		else if(dwResult2 != WAIT_TIMEOUT)
		VERIFY(FALSE);
		}
		*/

		//WAIT_OBJECT_0所有对象都发出信号
		if(dwResult == WAIT_OBJECT_0)
		{
			TBufferObj* pBufferObj	= pServer->GetFreeBufferObj();
			SOCKET soClient			= pServer->GetAcceptSocket();

			//投递一个连接接收SO_ACCEPT
			VERIFY(::PostAccept(pServer->m_pfnAcceptEx, pServer->m_soListen, soClient, pBufferObj) == NO_ERROR);

			/*
			if(::PostAccept(pServer->m_pfnAcceptEx, pServer->m_soListen, soClient, pBufferObj) != NO_ERROR)
			{
			pServer->DeleteBufferObj(pBufferObj);
			pServer->ReleaseAcceptSockets();
			pServer->Stop();

			TRACE1("-----> Accept Thread terminated (EC: %d) <-----\n", ::WSAGetLastError());
			break;
			}
			*/
		}
		else if(dwResult == WAIT_OBJECT_0 + 1)
		{//第一个参数发出了信号
			pServer->ReleaseAcceptSockets();

			TRACE1("---------------> Accept Thread 0x%08X stoped <---------------\n", ::GetCurrentThreadId());
			break;
		}
		else
			VERIFY(FALSE);
	}

	return 0;
}