int HandleIOProcessTCPServer::threadrun(void * pBuf) { while(TRUE) { // 等待网络事件 int nIndex = ::WSAWaitForMultipleEvents(nSocketCount+1,events, FALSE, WSA_INFINITE, FALSE); nIndex = nIndex - WSA_WAIT_EVENT_0; // 查看受信的事件对象 for(int i=nIndex; i<nSocketCount + 1; i++) { nIndex = ::WSAWaitForMultipleEvents(1, &events[i], TRUE, 1000, FALSE); if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT) { continue; } else { if(i == 0) // events[0]受信,重建数组 { RebuildEventArray(); // 如果没有客户I/O要处理了,则本线程退出 if(nSocketCount == 0||m_exitCode==1) { DestroyAllSocket(); _endthreadex(0); return 0; } ::WSAResetEvent(events[0]); } else// 处理网络事件 { // 查找对应的套节字对象指针,调用HandleIO处理网络事件 //nIndex-WSA_WAIT_EVENT_0 //WSA_MAXIMUM_WAIT_EVENTS PSOCKET_OBJ pSocket = (PSOCKET_OBJ)findSocket(events[i]); if(pSocket != NULL) { if(!HandleIO(pSocket)) RebuildEventArray(); } else printf(" Unable to find socket object \n "); } } } } }
int MightyTCPCompletionPortServer::WorkProcess() { PCompletionPort_BufObj pBuffer; DWORD dwKey; DWORD dwTrans; LPOVERLAPPED lpol; while(m_exitNotify==0) { // 在关联到此完成端口的所有套节字上等待I/O完成 BOOL bOK = ::GetQueuedCompletionStatus(m_hCompletionPort,&dwTrans, (LPDWORD)&dwKey, (LPOVERLAPPED*)&lpol, WSA_INFINITE); if(dwTrans == -1) // 用户通知退出 { ::ExitThread(0); } pBuffer = CONTAINING_RECORD(lpol, CompletionPort_BufObj, wsaol); int nError = NO_ERROR; if(!bOK) // 在此套节字上有错误发生 { SOCKET s; if(pBuffer->nOperation == OP_ACCEPT) { s =m_ListenSock; } else { if(dwKey == 0) break; s = ((PCompletionPortIOObject)dwKey)->s; } DWORD dwFlags = 0; if(!::WSAGetOverlappedResult(s, &pBuffer->wsaol, &dwTrans, FALSE, &dwFlags)) { nError = ::WSAGetLastError(); } } HandleIO(dwKey, pBuffer, dwTrans, nError); } return 0; }
void main() { // 创建监听套节字,绑定到本地端口,进入监听模式 int nPort = 4567; SOCKET sListen = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, //此三个参数与标准socket相同 NULL, //指定下层服务提供者,可以是NULL 0, //保留 WSA_FLAG_OVERLAPPED); //指定socket属性,要使用重叠I/O模型,必须指定WSA_FLAG_OVERLAPPED //如果使用socket则默认指定WSA_FLAG_OVERLAPPED //绑定并监听IP和端口 SOCKADDR_IN si; si.sin_family = AF_INET; si.sin_port = ::ntohs(nPort); si.sin_addr.S_un.S_addr = INADDR_ANY; ::bind(sListen, (sockaddr*)&si, sizeof(si)); ::listen(sListen, 200); // 为监听套节字创建一个SOCKET_OBJ对象 GetSocketObj函数仅仅开辟一个PSOCKET_OBJ内存并将套接字传入, PSOCKET_OBJ pListen = GetSocketObj(sListen); // 加载扩展函数AcceptEx GUID GuidAcceptEx = WSAID_ACCEPTEX; DWORD dwBytes; //套接字选项和I/O控制命令 此处用来获取AcceptEx函数指针 WSAIoctl(pListen->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), &pListen->lpfnAcceptEx, sizeof(pListen->lpfnAcceptEx), &dwBytes, NULL, NULL); g_pfnGetAcceptExSockaddrs = (LPFN_GETACCEPTEXSOCKADDRS)GetExtensionFuncPtr(pListen->s); // 创建用来重新建立g_events数组的事件对象 g_events[0] = ::WSACreateEvent(); // 在此可以投递多个接受I/O请求 投递5个接受连接请求 for(int i=0; i<5; i++) { PostAccept(GetBufferObj(pListen, BUFFER_SIZE)); } ::WSASetEvent(g_events[0]); while(TRUE) { int nIndex = ::WSAWaitForMultipleEvents(g_nBufferCount + 1, g_events, FALSE, WSA_INFINITE, FALSE); if(nIndex == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents() failed \n"); break; } nIndex = nIndex - WSA_WAIT_EVENT_0; for(int i=0; i<=nIndex; i++) { int nRet = ::WSAWaitForMultipleEvents(1, &g_events[i], TRUE, 0, FALSE); if(nRet == WSA_WAIT_TIMEOUT) continue; else { ::WSAResetEvent(g_events[i]); // 重新建立g_events数组 if(i == 0) { RebuildArray(); continue; } // 处理这个I/O PBUFFER_OBJ pBuffer = FindBufferObj(g_events[i]); if(pBuffer != NULL) { if(!HandleIO(pBuffer)) RebuildArray(); } } } } }