【网络编程】之九、事件选择WSAEventSelect
WSAEventSelect模型是类似于WSAAsyncSelect模型的另一个有用的异步I/O模型。它允许应用程序在一个或者多个套接字上接收以事件为基础的网络事件。 在这里,最主要的差别是在于网络事件会投递到一个事件对象句柄。并不是投递到一个窗口。
我们使用事件模型前,我们的应用程序针对使用的每一个套接字首先要创建一个事件对象:
#include <WinSock2.h>#include <iostream>using namespace std;#pragma comment(lib, "WS2_32.lib")int main(){WSAEVENT eventArray[1024];SOCKET sockArray[1024];int nEventTotal = 0;WSADATA wsadata;WORD sockVersion = MAKEWORD(2, 0);WSAStartup(sockVersion, &wsadata);SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(8888);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (bind(s, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){cout << "error" << endl;return 0;}listen(s, 5);WSAEVENT event = ::WSACreateEvent();::WSAEventSelect(s, event, FD_ACCEPT|FD_CLOSE);eventArray[nEventTotal] = event;sockArray[nEventTotal] = s;while(TRUE){// 在所有事件对象上等待int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);// 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态nIndex = nIndex - WSA_WAIT_EVENT_0;for(int i=nIndex; i<nEventTotal; i++){nIndex = ::WSAWaitForMultipleEvents(1, &eventArray[i], TRUE, 1000, FALSE);if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT){continue;}else{// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件WSANETWORKEVENTS event;::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);if(event.lNetworkEvents & FD_ACCEPT) // 处理FD_ACCEPT通知消息{if(event.iErrorCode[FD_ACCEPT_BIT] == 0){if(nEventTotal > WSA_MAXIMUM_WAIT_EVENTS){cout << " Too many connections! " << endl;continue;}SOCKET sNew = accept(sockArray[i], NULL, NULL);WSAEVENT event = ::WSACreateEvent();::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);// 添加到表中eventArray[nEventTotal] = event;sockArray[nEventTotal] = sNew; nEventTotal++;}}else if(event.lNetworkEvents & FD_READ) // 处理FD_READ通知消息{if(event.iErrorCode[FD_READ_BIT] == 0){char szText[256];int nRecv = ::recv(sockArray[i], szText, 256, 0);if(nRecv > 0) {szText[nRecv] = 0;cout << "接收到数据:" << szText << endl;}}}else if(event.lNetworkEvents & FD_CLOSE) // 处理FD_CLOSE通知消息{if(event.iErrorCode[FD_CLOSE_BIT] == 0){::closesocket(sockArray[i]);for(int j=i; j<nEventTotal-1; j++){eventArray[j] = eventArray[j+1];sockArray[j] = sockArray[j+1]; }nEventTotal--;i--;}}else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息{}}}}return 0;}2012/9/2
jofranks 于南昌