wsaeventselect 是 winsock 提供的一種非同步事件通知i/o模型,與 wsaasyncselect模型有些類似。
該模型同樣是接收 fd_*** 之類的網路事件,但是是通過事件物件控制代碼通知,而非像 wsaasyncselect一樣依靠windows的訊息驅動機制。
與wsaasyncselect模型相同,wsaeventselect將所有的socket事件分為如下型別:(共十種)
fd_read , fd_write , fd_oob , fd_accept, fd_connect , fd_close,
fd_qos , fd_group_qos , fd_routing_inte***ce_change , fd_address_list_change
還有乙個 fd_all_events 代表所有的事件
其中 fd_read 的定義如下:
#define fd_read_bit 0
#define fd_read (1 << fd_read_bit) // = 1
其他的定義也都類似,比如: fd_accept_bit = 3
但是並不是每一種socket都能發生所有的事件,比如監聽socket只能發生 fd_accept 和 fd_close 事件。
在wsaeventselect模型中,基本流程如下:
1. 建立乙個事件物件陣列,用於存放所有的事件物件;
2. 建立乙個事件物件(wsacreateevent);
3. 將一組你感興趣的socket事件與事件物件關聯(wsaeventselect),然後加入事件物件陣列;
4. 等待事件物件陣列上發生乙個你感興趣的網路事件(wsawaitformultipleevents);
5. 對發生事件的事件物件查詢具體發生的事件型別(wsaenumnetworkevents);
6. 針對不同的事件型別進行不同的處理;
7. 迴圈進行 .4
對於tcp服務端程式而言,在建立乙個監聽socket,繫結至某個埠然後監聽後,可以建立乙個事件物件然後與 fd_accept 和 fd_close 事件
關聯。在第6步時對於 fd_accept 事件可以將accept得到的socket關聯 fd_write,fd_read,fd_close事件後加入事件物件陣列。
wsaevent wsacreateevent(
void);
建立乙個 事件物件,實際上 wsaevent就是乙個 handle
int wsaeventselect(
_in_ socket s,
//需要關聯的socket
_in_ wsaevent heventobject,
//需要關聯的事件物件
_in_
long lnetworkevents
//感興趣的網路事件,不同的事件可以用 | 合併, fd_all_events 代表所有的事件
);函式執行成功將返回 0 ,否則返回 socket_error, 可呼叫wsagetlasterror() 檢視具體的錯誤**
dword wsawaitformultipleevents(
_in_ dword cevents,
//事件物件陣列的數量
_in_
const wsaevent *lphevents,
//事件物件陣列
_in_ bool fwaitall,
//是否等待所有的事件物件受信,顯然一般情況下是false
_in_ dword dwtimeout,
//超時時限,單位是毫秒,wsa_infinite 為無窮大
_in_ bool falertable
//該模型下忽略,應該設定為false);
如果執行失敗返回 wsa_wait_io_completion ; 如果是超時,則返回 wsa_wait_timeout
如果 函式執行成功將會返回乙個值,分布在 區間 [ wsa_wait_event_0 ,(wsa_wait_event_0+cevents-1) ] 內
也就是說返回值 nret-wsa_wait_event_0 將是發生事件的物件在事件物件陣列中的下標。
int wsaenumnetworkevents(
_in_ socket s,
//發生事件的socket
_in_ wsaevent heventobject,
//發生事件的事件物件
_out_ lpwsanetworkevents lpnetworkevents
//發生的網路事件
);如果該函式執行成功將會返回0,然後可以通過查詢網路事件判斷到底發生了什麼事件。
wsanetworkevents的定義如下:
typedef
struct _wsanetworkevents wsanetworkevents, far * lpwsanetworkevents;
比如當發生 fd_read 事件時, 那麼 networkevent.lnetworkevents&fd_read 將為真,同時 networkevent.ierrorcode[fd_read_bit]
標明了此時的錯誤**。
**示例:(你還需要乙個 client程式,自己寫或者找吧)
#include #include #include #pragma comment(lib,"ws2_32.lib")
using std::cout;
using std::cin;
using std::endl;
using std::ends;
void wsaeventserversocket()
{ socket server = ::socket(af_inet,sock_stream,ipproto_tcp);
if(server == invalid_socket){
cout<
cout<
cout<
// 解釋一下,為什麼我在 socket函式前面加上 ::
因為我前面寫的時候本來用了thread庫準備開乙個執行緒執行server,另乙個執行client。
結果 用了 using namespace std; 後,正好引入了bind函式(std的那個模板)把 socket的bind給覆蓋了,
然後就一直是 錯誤了,查下錯誤**是 10022(無效引數),檢查時才發現的。
WSAEventSelect 功能描述
wsaeventselect 簡述 確定與所提供的fd 網路事件集合相關的乙個事件物件。include int wsaapi wsaeventselect socket s,wsaevent heventobject,long lnetworkevents s 乙個標識套介面的描述字。lnetwor...
封裝WSAEventSelect模型
include include pragma comment lib,ws2 32.lib pragma once class casynchandler virtual casynchandler virtual int acceptnotify socket hsocket,const char...
WSAEventSelect程式設計模型實現
伺服器端 把 include 放到最前面 至於原因,那是因為windows.h這個標頭檔案已經包含了winsock.h 和winsock2.h貌似有衝突 include include include include winsock.h pragma comment lib,wsock32 prag...