欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WSAEventSelect模型

程序员文章站 2022-04-24 14:33:37
...

4步走:

1.//1. 事件句柄和套接字句柄表

2.//2. 创建事件对象,并关联到新的套接字上

3.//3. 在所有事件上等待 //对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态

4//获取来到的消息,WSAEnumNetworkEvents会自动重置受信事件

上代码:

#include "InitSock.h"
#include <stdio.h>
int main()
{
	CInitSock initSock;
	//1. 事件句柄和套接字句柄表
	WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
	SOCKET socketArray[WSA_MAXIMUM_WAIT_EVENTS];
	int nEventTotal = 0;


	USHORT nPort = 9999;
	SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sListen)
	{
		return -1;
	}
	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)
	{
		return -1;
	}
	::listen(sListen, 5);

	//2. 创建事件对象,并关联到新的套接字上
	WSAEVENT event = ::WSACreateEvent();
	::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE);

	//添加到列表中
	eventArray[nEventTotal] = event;
	socketArray[nEventTotal] = sListen;
	nEventTotal++;

	//处理网络事件
	while (TRUE)
	{
		//3. 在所有事件上等待
		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(socketArray[i], eventArray[i], &event);
				if (event.lNetworkEvents & FD_ACCEPT) //接收到连接
				{
					MessageBox(NULL, "fd_accept", "",MB_OK);
					if (event.iErrorCode[FD_ACCEPT_BIT] == 0) //没出错
					{
						if (nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)
						{
							printf("too many connections...");
						}
						SOCKET sNew = ::accept(socketArray[i], NULL, NULL);
						WSAEVENT event = WSACreateEvent();
						::WSAEventSelect(sNew, event, FD_READ|FD_WRITE|FD_CLOSE);

						//添加到列表
						eventArray[nEventTotal] = event;
						socketArray[nEventTotal] = sNew;
						nEventTotal++;
					}
				}
				else if (event.lNetworkEvents & FD_READ)
				{
					if (event.iErrorCode[FD_READ_BIT] == 0)
					{
						char szContent[512]={0};
						int nRecv= ::recv(socketArray[i], szContent, 512, 0);
						if (nRecv > 0)
						{
							szContent[nRecv] = '\0';
							printf("收到数据 :%s", szContent);
						}
					}
				}
				else if (event.lNetworkEvents & FD_CLOSE)
				{
					if (event.iErrorCode[FD_CLOSE_BIT] == 0)
					{
						::closesocket(socketArray[i]);
						for (int j=i;j<nEventTotal-1;j++)
						{
							socketArray[j] = socketArray[j+1];
							eventArray[j] = eventArray[j+1];
						}
						nEventTotal--;
					}
				}
				else if (event.lNetworkEvents & FD_WRITE)
				{
					char szContent[] = "server writed";
					::send(socketArray[i], szContent, sizeof(szContent), 0);
				}
			}
		}
	}
	return 0;
}