WSAEVENTSELECT模型

WSAEventSelect是一種非常有用的異步I/O模型,一般使用在客戶端.該模型允許應用程式同時管理一個或多個套接字,並能夠接收以事件對象為基礎的網路事件通知.

簡述

確定與所提供的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)

相關詞條

相關搜尋

熱門詞條

聯絡我們