WSAEventSelect模型詳解

2021-07-30 22:22:35 字數 3252 閱讀 7149

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...