WinSock I/O 模型

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

你可能感兴趣的:(windows,socket,winsock,IO模型)