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; }
// 完成端口的工作线程 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; }