#include <stdio.h>
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <map>
#pragma comment(lib, "WS2_32")
using namespace std;
typedef map<WSAEVENT, SOCKET> SockMap;
class CInitSock{
public:
CInitSock()
{
WSADATA wsaData;
if(::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
exit(0);
}
}
virtual ~CInitSock()
{
::WSACleanup();
}
};
int main()
{
CInitSock theSock;
int nEventTotal = 0;
bool bRebuild = true;
USHORT nPort = 4567;
SockMap skmap;
WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS];
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(nPort);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
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);
// 添加到表中
skmap.insert(make_pair<WSAEVENT, SOCKET>(event, sListen));
// 处理网络事件
while(TRUE)
{
if(bRebuild)
{
nEventTotal = 0;
for(SockMap::iterator it = skmap.begin(); it != skmap.end(); ++it)
{
eventArray[nEventTotal] = it->first;
sockArray[nEventTotal] = it->second;
nEventTotal++;
}
bRebuild = false;
}
// 在所有事件对象上等待
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, 0, FALSE);
if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)
{
continue;
}
else
{
bool remove = false;
// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTS event;
::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);
if(event.lNetworkEvents & FD_ACCEPT) // 处理FD_ACCEPT通知消息
{
if(event.iErrorCode[FD_ACCEPT_BIT] == 0)
{
if(skmap.size() >= WSA_MAXIMUM_WAIT_EVENTS)
{
printf(" Too many connections! \n");
continue;
}
SOCKET sNew = ::accept(sockArray[i], NULL, NULL);
WSAEVENT event = ::WSACreateEvent();
::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);
// 添加到表中
skmap.insert(make_pair<WSAEVENT, SOCKET>(event, sNew));
bRebuild = true;
//printf("new socket size: %d\n", skmap.size());
}
else
remove = true;
}
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);
//::send(sockArray[i], szText, nRecv, 0);
}
}
else
remove = true;
}
if(event.lNetworkEvents & FD_CLOSE) // 处理FD_CLOSE通知消息
{
if(event.iErrorCode[FD_CLOSE_BIT] == 0)
{
char szText[256];
int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);
if( nRecv > 0)
{
szText[nRecv] = '\0';
printf("接收到数据2:%s \n", szText);
}
}
remove = true;
}
if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
}
if(remove)
{
::closesocket(sockArray[i]);
::CloseHandle(eventArray[i]);
skmap.erase(eventArray[i]);
bRebuild = true;
printf("close sock error, left %d\n", skmap.size());
}
}
}
}
return 0;
}
WSAEventSelect的使用
最新推荐文章于 2021-04-17 21:17:03 发布