Windows IO模型-WSAEventSelect模型(非同步阻塞模型)
事件選擇(WSAEventSelect)模型:基於事件通知,事件是一個有作業系統管理的核心物件,當前系統基於事件機制,該模型則可以使用,事件兩種狀態,有訊號和無訊號,檢測事件,若有訊號則進行相應處理。
優點:(1)可以在非視窗的Windows Socket程式中,實現多個套接字的管理。
缺點:(1)不能同時處理多個Socket,有數量限制。要麼Wait一個事件對應一個執行緒,(2)仍然屬於阻塞模型,非同步阻塞模型。(3)每個WSAEventSelect模型最多隻能管理64個套接字。當應用程式中要管理多餘64個套接字時,就需要額外建立執行緒。
3.1、建立一個無訊號的事件 WSAEVENT------HANDLE
WSAEVENT we=WSACreateEvent();
3.2、向Windows註冊網路事件。
int WSAEventSelect(
_In_ SOCKET s, //監控的網路事件
_In_ WSAEVENT hEventObject, // 建立的事件
_In_ long lNetworkEvents //網路事件型別
);
//註冊完的事件加入到監測的事件陣列,將socket加入到對應的socket陣列。
3.3、建立執行緒---看事件是否有訊號,
m_hthread = (HANDLE) _beginthread(NULL,0,&threadRecv,this,0,NULL);
DWORD WINAPI threadRecv( LPVOID lpvoid) //執行緒的入口函式
{
UDPNet * pthis = (UDPNet *)lpvoid;
char szBuf[_DEFAULT_PACK] = {0};
Sockaddr_in addrClient;
Int nSize = sizeof(sockaddr_in);
While(pthis->m_bFlag)
{
WSAWaitForMultipleEvents(...);
}
return 0;
}
3.4、檢視是否有事件發生
DWORD WSAWaitForMultipleEvents
DWORD cEvents, // 等候事件的總數量,陣列長度
const WSAEVENT* lphEvents, // 事件陣列的指針
BOOL fWaitAll,// 若為TRUE,需所有事件發生才會返回
DWORD dwTimeout, // 超時時間,
BOOL fAlertable//指定執行緒是否為alertable等待態);
引數介紹:
BOOL fWaitAll, // 這個要多說兩句: // 如果設定為TRUE,則事件陣列中所有事件被傳信的時候函式才會返回 // FALSE則任何一個事件被傳信函式都要返回 //如果為FALSE,返回值減去WSA_WAIT_EVENT_0,為當前事件在陣列中的索引。只能返回一個
DWORD dwTimeout, // 超時時間,如果超時,函式會返回 WSA_WAIT_TIMEOUT//如果設定為0,函式會立即返回 //如果設定為WSA_INFINITE只有在某一個事件被傳信後才會返回, //則WSAWaitForMultipleEvents永遠等待,不會出現超時現象。
BOOL fAlertablefAlertable引數,在我們使用 WSAEventSelect模型的時候,它是可以忽略的,且應設為 FALSE。該引數主要用於在重疊式I/O 模型中,在完成例程的處理過程中
3.5、 發生事件的網路事件型別--判斷當前發生什麼網路事件
int WSAEnumNetworkEvents(
_In_ SOCKET s, //哪個socket
_In_ WSAEVENT hEventObject, //發生什麼事件
_Out_ LPWSANETWORKEVENTS lpNetworkEvents //獲得發生的網路事件型別
);
//返回值為0,則成功,
typedef struct _WSANETWORKEVENTS{
long lNetworkEvents; //網路事件,如FD_READ 、FD_WRITE
int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;