套接字IO模型(三) WSAEventSelect模型
http://www.cnblogs.com/NeuqUstcIim/archive/2008/08/14/1268214.html
WSAEventSelect模型類似WSAAsynSelect模型,但最主要的區(qū)別是網(wǎng)絡(luò)事件發(fā)生時會被發(fā)送到一個事件對象句柄,而不是發(fā)送到一個窗口。這樣可能更加的好,對于服務(wù)器端的程序來說。
使用步驟如下:
a、 創(chuàng)建事件對象來接收網(wǎng)絡(luò)事件:
WSAEVENT WSACreateEvent( void );
該函數(shù)的返回值為一個事件對象句柄,它具有兩種工作狀態(tài):已傳信(signaled)和未傳信(nonsignaled)以及兩種工作模式:人工重設(shè)(manual reset)和自動重設(shè)(auto reset)。默認(rèn)未未傳信的工作狀態(tài)和人工重設(shè)模式。
b、將事件對象與套接字關(guān)聯(lián),同時注冊事件,使事件對象的工作狀態(tài)從未傳信轉(zhuǎn)變未已傳信。
int WSAEventSelect( SOCKET s,WSAEVENT hEventObject,long lNetworkEvents );
s為套接字
hEventObject為剛才創(chuàng)建的事件對象句柄
lNetworkEvents為掩碼,定義如上面所述
c、I/O處理后,設(shè)置事件對象為未傳信
BOOL WSAResetEvent( WSAEVENT hEvent );
Hevent為事件對象
成功返回TRUE,失敗返回FALSE。
d、等待網(wǎng)絡(luò)事件來觸發(fā)事件句柄的工作狀態(tài):
DWORD WSAWaitForMultipleEvents( DWORD cEvents,const WSAEVENT FAR * lphEvents, BOOL fWaitAll,DWORD dwTimeout, BOOL fAlertable );
lpEvent為事件句柄數(shù)組的指針
cEvent為為事件句柄的數(shù)目,其最大值為WSA_MAXIMUM_WAIT_EVENTS
fWaitAll指定等待類型:TRUE:當(dāng)lphEvent數(shù)組重所有事件對象同時有信號時返回;
FALSE:任一事件有信號就返回。
dwTimeout為等待超時(毫秒)
fAlertable為指定函數(shù)返回時是否執(zhí)行完成例程
nIndex=WSAWaitForMultipleEvents(…);
MyEvent=EventArray[Index- WSA_WAIT_EVENT_0];
事 件選擇模型也比較簡單,實現(xiàn)起來也不是太復(fù)雜,它的基本思想是將每個套接字都和一個WSAEVENT對象對應(yīng)起來,并且在關(guān)聯(lián)的時候指定需要關(guān)注的哪些網(wǎng) 絡(luò)事件。一旦在某個套接字上發(fā)生了我們關(guān)注的事件(FD_READ和FD_CLOSE),與之相關(guān)聯(lián)的WSAEVENT對象被Signaled。程序定義 了兩個全局?jǐn)?shù)組,一個套接字?jǐn)?shù)組,一個WSAEVENT對象數(shù)組,其大小都是MAXIMUM_WAIT_OBJECTS(64),兩個數(shù)組中的元素一一對 應(yīng)。
同樣的,這里的程序沒有考慮兩個問題,一是不能無條件的調(diào)用accept,因為我們支持的并發(fā)連接數(shù)有限。解決方法是將套接字按 MAXIMUM_WAIT_OBJECTS分組,每MAXIMUM_WAIT_OBJECTS個套接字一組,每一組分配一個工作者線程;或者采用 WSAAccept代替accept,并回調(diào)自己定義的Condition Function。第二個問題是沒有對連接數(shù)為0的情形做特殊處理,程序在連接數(shù)為0的時候CPU占用率為100%。
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_RE
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 }
posted on 2011-08-18 16:08 厚積薄發(fā) 閱讀(576) 評論(0) 編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程