1、select 模型
int select( _In_ int nfds, _Inout_ fd_set *readfds, _Inout_ fd_set *writefds, _Inout_ fd_set *exceptfds, _In_ const struct timeval *timeout );
eg:获取读集
fd_set fds; int nReady; timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(pSocket->m_hSocket, &fds); nReady = select(0, &fds, NULL, NULL, &timeout); if (nReady == SOCKET_ERROR) nErrorCode = WSAGetLastError(); if ((nReady == 1) || (nErrorCode != 0)) pSocket->OnReceive(nErrorCode);
2、WSAAsyncSelect异步I/O模型
这是MFC的CAsyncSocket类采用的模型
int WSAAsyncSelect( _In_ SOCKET s, _In_ HWND hWnd, _In_ unsigned int wMsg, _In_ long lEvent );
此函数有个窗口句柄,底层把网络事件发到该窗体的消息队列中。
eg:return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow, WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;
3、WSAEventSelect事件选择模型
类似于select模型
int WSAEventSelect( _In_ SOCKET s, _In_ WSAEVENT hEventObject, _In_ long lNetworkEvents );
for example:// Associate event types FD_ACCEPT and FD_CLOSE // with the listening socket and NewEvent WSAEventSelect( ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE); //---------------------- // Listen for incoming connection requests // on the created socket if (listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR) printf("Error listening on socket.\n");
4、重叠I/O模型,有事件通知和完成例程
事件通知方式:主要是创建事件数组,初始化重叠结构,与调用WSAWaitForMultipleEvents函数
eg:
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE); // Reset the signaled event bResult = WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]); if (bResult == FALSE) {wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());} //----------------------------------------- // Determine the status of the overlapped event bResult = WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags); if (bResult == FALSE) {wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());}
完成例程方式:主要是用回调函数处理The prototype of the completion routine is as follows.
void CALLBACK CompletionROUTINE( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags );
在完成例程中,系统在网络操作完成以后会自动调用你提供的回调函数
如WSARecv的参数:int WSARecv( _In_ SOCKET s, _Inout_ LPWSABUF lpBuffers, _In_ DWORD dwBufferCount, _Out_ LPDWORD lpNumberOfBytesRecvd, _Inout_ LPDWORD lpFlags, _In_ LPWSAOVERLAPPED lpOverlapped, _In_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
5、完成端口(IOCP)模型
主要使用函数:
HANDLE WINAPI CreateIoCompletionPort( _In_ HANDLE FileHandle, _In_opt_ HANDLE ExistingCompletionPort, _In_ ULONG_PTR CompletionKey, _In_ DWORD NumberOfConcurrentThreads );
例如:
HANDLE hIOCP = INVALID_HANDLE_VALUE; hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (hIOCP == NULL) { printf_s("CreateIoCompletionPort Failed ...\n"); nRetCode = 12; break; }
VERIFY(CreateIoCompletionPort((HANDLE)hSocketAccepted, hIOCP, (ULONG_PTR)lpIOCPData, 0) == hIOCP);
if (GetQueuedCompletionStatus(hCompletionPort, &dwNumberOfBytes, &nCompletionKey, &lpOvIOCP, INFINITE))
6、Poll模型(高版本windows系统支持,类似于linux下的epoll)
typedef struct pollfd { SOCKET fd; short events; short revents; } WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD; int WSAAPI WSAPoll( _Inout_ WSAPOLLFD fdarray[], _In_ ULONG nfds, _In_ INT timeout );
Minimum supported client: Windows Vista
Minimum supported server: Windows Server 2008