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;
}