WSAEventSelect 模型

来源:互联网 发布:知乎举报是匿名的吗 编辑:程序博客网 时间:2024/05/05 06:17


Winsock提供了另一种有用的异步事件通知I/O模型——WSAEventSelect模型。这个模型与WSAAsyncSelect模型类似,允许应用程序在一个或者多个套接字上接收基于事件的网络通知。它与WSAAsyncSelect 模型类似是因为它也接收FD_XXX类型的网络事件,不过并不是依靠Windows的消息驱动机制,而是经由事件对象句柄通知。 



//////////////////////////////////////////////////// WSAEventSelect#include "../common/initsock.h"#include <stdio.h>#include <iostream.h>#include <windows.h>CInitSock initSock;// 初始化Winsock库int main(){// 事件句柄和套接字句柄表WSAEVENTeventArray[WSA_MAXIMUM_WAIT_EVENTS];SOCKETsockArray[WSA_MAXIMUM_WAIT_EVENTS];int nEventTotal = 0;USHORT nPort = 4567;// 服务器监听端口// 创建监听套接字SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(nPort);sin.sin_addr.S_un.S_addr = INADDR_ANY;// 绑定端口if (::bind(sListen, (sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR) {printf("Failed bind() \n");return -1;}// 进入监听::listen(sListen, 5);// 创建事件对象,并关联到新的套接字WSAEVENT event = ::WSACreateEvent();// 将网络事件和事件对象关联起来;::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE);// 添加到表中eventArray[nEventTotal] = event;sockArray[nEventTotal] = sListen;nEventTotal++;// 处理网络事件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函数会自动重置受信事件;// 找到与之对应的套接字,WSAEnumNetworkEvents查看发生了什么网络事件;WSANETWORKEVENTS event;::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);if (event.lNetworkEvents & FD_ACCEPT)// 处理FD_ACCEPT通知消息{if (event.iErrorCode[FD_ACCEPT_BIT] == 0)// FD_ACCEPT未出错{if (nEventTotal > WSA_MAXIMUM_WAIT_EVENTS) {printf(" Too many connections");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, strlen(szText), 0);if (nRecv > 0) {szText[nRecv] = '\0';printf("接受到数据:%s \n", szText);}}}else if (event.lNetworkEvents & FD_CLOSE)// 处理FD_CLOSE通知消息  {if (event.iErrorCode[FD_CLOSE_BIT] == 0) {::closesocket(sockArray[i]);for(int j = i; j < nEventTotal; j++)// 删除数组元素;{sockArray[j] = sockArray[j+1];}nEventTotal--;}}else if (event.lNetworkEvents & FD_WRITE)//  处理FD_WRITE通知消息  {}}}}return 0;}


0 0
原创粉丝点击