通訊端IO模型(三) WSAEventSelect模型

來源:互聯網
上載者:User
連結:http://www.cnblogs.com/NeuqUstcIim/archive/2008/08/14/1268214.html通訊端IO模型(三)
WSAEventSelect模型

WSAEventSelect模型類似WSAAsynSelect模型,但最主要的區別是網路事件發生時會被發送到一個事件物件控點,而不是發送到一個視窗。這樣可能更加的好,對於伺服器端的程式來說。

使用步驟如下:

a、 建立事件對象來接收網路事件:

WSAEVENT WSACreateEvent( void );

該函數的傳回值為一個事件物件控點,它具有兩種工作狀態:已傳信(signaled)和未傳信(nonsignaled)以及兩種工作模式:人工重設(manual
reset)和自動重設(auto reset)。預設未未傳信的工作狀態和人工重設模式。

 

b、將事件對象與通訊端關聯,同時註冊事件,使事件對象的工作狀態從未傳信轉變未已傳信。

int WSAEventSelect( SOCKET s,WSAEVENT hEventObject,long lNetworkEvents );

s為通訊端
hEventObject為剛才建立的事件物件控點

lNetworkEvents為掩碼,定義如上面所述

 

c、I/O處理後,設定事件對象為未傳信
BOOL WSAResetEvent( WSAEVENT hEvent
);
Hevent為事件對象

成功返回TRUE,失敗返回FALSE。

 

d、等待網路事件來觸發事件控制代碼的工作狀態:

DWORD WSAWaitForMultipleEvents( DWORD cEvents,const WSAEVENT FAR * lphEvents,
BOOL fWaitAll,DWORD dwTimeout, BOOL fAlertable
);
lpEvent為事件控制代碼數組的指標
cEvent為為事件控制代碼的數目,其最大值為WSA_MAXIMUM_WAIT_EVENTS

fWaitAll指定等待類型:TRUE:當lphEvent數組重所有事件對象同時有訊號時返回;
FALSE:任一事件有訊號就返回。
dwTimeout為等待逾時(毫秒)

fAlertable為指定函數返回時是否執行完成常式

 

nIndex=WSAWaitForMultipleEvents(…);

MyEvent=EventArray[Index- WSA_WAIT_EVENT_0];

 

 


件選擇模型也比較簡單,實現起來也不是太複雜,它的基本思想是將每個通訊端都和一個WSAEVENT對象對應起來,並且在關聯的時候指定需要關注的哪些網
絡事件。一旦在某個通訊端上發生了我們關注的事件(FD_READ和FD_CLOSE),與之相關聯的WSAEVENT對象被Signaled。程式定義
了兩個全域數組,一個通訊端數組,一個WSAEVENT對象數組,其大小都是MAXIMUM_WAIT_OBJECTS(64),兩個數組中的元素一一對
應。
同樣的,這裡的程式沒有考慮兩個問題,一是不能無條件的調用accept,因為我們支援的並發串連數有限。解決方案是將通訊端按
MAXIMUM_WAIT_OBJECTS分組,每MAXIMUM_WAIT_OBJECTS個通訊端一組,每一組分配一個工作者線程;或者採用
WSAAccept代替accept,並回調自己定義的Condition
Function。第二個問題是沒有對串連數為0的情形做特殊處理,程式在串連數為0的時候CPU佔用率為100%。

 

 1 SOCKET      
Socket[WSA_MAXIMUM_WAIT_EVENTS];
 2 WSAEVENT   Event[WSA_MAXINUM_WAIT_EVENTS];
 3 SOCKET    Accept, Listen;
 5 DWORD     EventTotal = 0;
 6 DWORD     Index;
 7 
 8 //Set up a TCP socket for listening on port 5150
 9  Listen = socket(PF_INET,SOCK_STREAM,0);
10 
11 InternetAddr.sin_family      = AF_INET;
12 InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
13 InternetAddr.sin_port        = htons(5150);
14 
15 bind(Listen,(PSOCKADDR) &InternetAddr,sizeof(InternetAddr));
16 
17 NewEvent = WSACreateEvent();
18 
19 WSAEventSelect( Listen, NewEvnet, FD_ACCEPT|FD_CLOSE);
20 
21 listen(Listen,5);
22 
23 Socket[EventTotal] = Listen;
24 Event[EventTotal] = NewEvent;
25 EventTotal++;
26 
27 while (TRUE)
28 {
29     //Wait for network events on all sockets
30     Index = WSAWaitForMultipleEvents(EventTotal,EventArray,FALSE, WSA_INFINITE,FALSE);
31 
32     WSAEnumNewWorkEvents(SocketArray[Index-WSA_WAIT_EVENT_0],
33         EventArray[Index-WSA_WAIT_EVENT_0],
34         &NetworkEvents);
35     //Check for FD_ACCEPT messages
36     if ( NetworkEvents.lNetworkEvents  &  FD_ACCEPT )
37     {
38         if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] !=0)
39         {
40             //Error
41             break;
42         }
43         //Accept a new connection and add it to the socket and event lists
44          Accept = accept(SocketArray[ Index - WSA_WAIT_EVENT_0],NULL,NULL);
45 
46         //We cannot process more than WSA_MAXIMUM_WAIT_EVENTS sockets ,
47         //so close the accepted socket
48         if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS)
49         {
50             printf("..");
51             closesocket (Accept);
52             break;
53         }
54         NewEvent = WSACreateEvent();
55 
56         WSAEventSelect( Accept,NewEvent, FD_READ|FD_WRITE| FD_CLOSE);
57 
58         Event[EventTotal] = NewEvent;
59         Socket[EventTotal]=  Accept;
60         EventTotal++;
61         prinrt("Socket %d connect/n",Accept);
62     }
63     //Process FD_READ notification
64     if ( NetworkEvents.lNetwoAD)rkEvents & FD_R E
65     {
66         if (NetworkEvents.iErrorCode[FD_READ_BIT !=0])
67         {
68             //Error
69             break;
70         }
71 
72         //Read data from the socket
73         recv(Socket[ Index- WSA_WAIT_EVENT_0],buffer,sizeof(buffer),0);
74     }
75     //process FD_WRITE notitication
76     if ( NetworkEvents.lNetworkEvents & FD_WRITE)
77     {
78         if (NetworkEvents.iErrorCode[FD_WRITE_BIT] !=0)
79         {
80             //Error
81             break;
82         }
83         send(Socket[ Index- WSA_WAIT_EVENT_0],buffer,sizeof(buffer),0);
84     }
85     if ( NetworkEvents.lNetworkEvents  &  FD_CLOSE)
86     {
87         if(NetworkEvents.iErrorCode[FD_CLOSE_BIT] !=0)
88         {
89             //Error
90             break;
91         }
92         closesocket (Socket[Index-WSA_WAIT_EVENT_0]);
93         //Remove socket and associated event from the Socket and Event arrays and
94         //decrement eventTotal
95         CompressArrays(Event,Socket,& EventTotal);
96     }
97 }  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.