【轉】WSAEVENTSELECT模型-簡述

確定與所提供的FD_XXX網絡事件集合相關的一個事件對象。
  #include 
  int WSAAPI WSAEventSelect ( SOCKET s, WSAEVENT
  hEventObject, long lNetworkEvents );
  s:一個標識套接口的描述字。
  hEventObject:一個句柄,用於標識與所提供的FD_XXX網絡事件集合相關的一個事件對象。
  lNetworkEvents:一個屏蔽位,用於指定感興趣的FD_XXX網絡事件組合。
  返回值:
  如果應用程序指定的網絡事件及其相應的事件對象成功設置,則返回0。否則的話,將返回INVALID_SOCKET錯誤,應用程序可通過WSAGetLastError()來獲取相應的錯誤代碼。
  在使用select()和WSAAsyncSelect()函數時,WSAEventSelect()常用來決定何時進行數據傳送操作(如send()或recv()),並期望能立即成功。但是一個穩定的應用程序應該做好這樣的準備,即事件對象被設置,並且一個WinSock調用以WSAEWOULDBLOCK立即返回 。舉例來說,有可能發生下述操作序列:
  (i) 套接口s上到達數據;WinSock設置了WSAEventSelect事件對象。
  (ii) 應用程序進行其他操作。
  (iii) 在進行操作時,應用程序調用了ioctlsocket(s, FIONREAD...)並發現有數據可讀。
  (iv) 應用程序調用一個recv(s,...)來讀取數據。
  (v) 最後應用程序等待WSAEventSelect()所指定的數據對象,該數據對象指出數據可讀。
  (vi) 應用程序調用recv(s,...),但以WSAEWOULDBLOCK錯誤失敗。
  其他的操作序列也是可能的。
  成功地記錄了網絡事件的發生(通過設置內部網絡事件記錄的相應位),並且將相應的事件對象設置了信號後,不會對該網絡事件作進一步的操作,直到應用程序調用了相應的函數顯式地重新允許該網絡事件及相應事件對象的信號。
  網絡事件                                        重新允許函數
  FD_READ                                recv() 或 recvfrom()
  FD_WRITE                                send() 或 sendto()
  FD_OOB                                        recv()
  FD_ACCEPT                                accept() 或WSAAccept(),直到返回的錯誤代碼爲 WSATRY_AGAIN,指明條件函數返回CF_DEFER。
  FD_CONNECT                        NONE
  FD_CLOSE                                NONE
  FD_QOS                                        用SIO_GET_QOS 命令調用WSAIoctl()。
  FD_GROUP_QOS                        用SIO_GET_GROUP_QOS命令調用WSAIoctl()。
  錯誤代碼:
  WSANOTINITIALISED                在調用本API之前應成功調用WSAStartup()。
  WSAENETDOWN                        網絡子系統失效。
  WSAEINVAL                                參數中有非法值,或者指定的套接口處於非法狀態。
  WSAEINPROGRESS                一個阻塞的WinSock調用正在進行中,或者服務提供者仍在處理一個回調函數
  WSAENOTSOCK                        描述字不是一個套接口。
另請參閱:WSACloseEvent() ,WSACreateEvent(),WSAEnumNetworkEvents(),WSAGetOverlappedResult(),WSAWaitForMultipleEvents().


它允許程序在一個套接字上接收以事件爲基礎的網絡事件通知。
事件對象
       該模型要求程序對打算使用的每個套接字首先創建一個事件對象,方法是調用WSACreateEvent函數
WSAEVENT WSACreateEvent( void );
該函數返回創建好的事件對象。
        事件對象創建好後,必須將其與某個套接字關聯在一起,同時註冊感興趣的網絡事件類型。需調用WSAEventSelect函數。
int WSAEventSelect(
    SOCKET    sock,   /* 套接字 */
    WSAEVENT hEvent,   /* 事件對象 */
    long   lNetworkEvents /* 對應一個"位掩碼",指定感興趣的網絡事件類型 */ 
    );
創建的事件擁有兩種工作狀態和兩種模式。
工作狀態 : 已傳信和未傳信
工作模式 : 人工重設和自動重設
由WSACreateEvent創建的事件對象,默認工作狀態爲"未傳信",工作模式爲"人工重設",當網絡事件觸發了與套接字關聯在一起的事件對象時,工作狀態會轉變爲"已傳信",而在完成了一個I/O請求的處理之後,因爲工作模式爲"人工重設",因此,程序需要將工作狀態從"已傳信"改變爲"未傳信",使用WSAResetEvent函數
BOOL WSAResetEvent( WSAEVENT hEvent );
當程序不在對事件對象進行處理時,應調用WSACloseEvent函數將其關閉
BOOL WSACloseEvent( WSAEVENT hEvent );
套接字與事件對象關聯在一起後,便可開始進行I/O操作,方法是等待一個或多個事件對象,並在事先指定的一個或所有句柄進入"已傳信"狀態,或在超過了一個規定的時間間隔後,立即返回。使用WSAWaitForMultipleEvents函數
DWORD WSAWaitForMultipleEvents(
   DWORD cEvents,   /* 指定lphEvents的數量,最大爲WSA_MAXIMUM_WAIT_EVENTS(64) */
   const WSAEVENT *lphEvents, /* 事件對象數組 */ 
   BOOL fWaitAll,
   DWORD dwTimeout,   /* 等待時間,爲0,立即返回,爲WSA_INFINITE,永不返回 */
   BOOL fAlertable   /* 可設爲FALSE */
     );
fWaitAll : 指定如何等待lphEvents數組內的事件對象,爲TRUE時,只有當所有事件對象都進入"已傳信"時,纔會返回,若爲FALSE時,只要一個事件進入"已傳信"狀態,就返回,通常設爲FALSE
返回值:返回發生網絡事件的事件對象索引
當發生網絡事件後,接下來可調用WSAEnumNetworkEvents函數來檢查發生了什麼類型的網絡事件
int WSAEnumNetworkEvents(
   SOCKET sock,
   WSAEVENT hEvent,
   LPWSANETWORKEVENTS lpNetworkEvents
    );
lpNetworkEvents : 爲一個結構,內包含發生的事件及可能的錯誤代碼
typedef struct _WSANETWORKEVENTS
{
long lNetworkEvents;    /* 發生的網絡事件 */
int iErrorCode[FD_MAX_EVENTS]; /* 可能的錯誤代碼 */
}WSANETWORKEVENTS,*LPWSANETWORKEVENTS;
iErrorCode : 指定錯誤代碼數組,其索引名爲事件類型名+'_BIT'(如FD_READ_BIT)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章