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