#include "StdAfx.h"
#include "EventSocket.h"
CEventSocket::CEventSocket(void)
{
WSADATA wsaData;
if( (WSAStartup(MAKEWORD(2,2), &wsaData)) != 0 )
TRACE(_T("WSAStartup Failed"));
m_nEventTotal = 0;
m_hWkThread = NULL;
}
CEventSocket::~CEventSocket(void)
{
StopListen();
WSACleanup();
}
BOOL CEventSocket::ListenOn(int port, int sockType, int protocol)
{
if (m_hWkThread)
return FALSE;
SOCKADDR_IN skAddr;
skAddr.sin_family = AF_INET;
skAddr.sin_addr.s_addr = ADDR_ANY;
skAddr.sin_port = htons(port);
SOCKET sk = WSASocket(AF_INET, sockType, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
if (sk == INVALID_SOCKET)
{
TRACE(_T("WSASocket Failed"));
return FALSE;
}
if( bind(sk, (PSOCKADDR)&skAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR )
{
TRACE(_T("Server Soket Bind Failed"));
closesocket(sk);
return FALSE;
}
if(listen(sk, MAX_PENDING_CONNECTIONS) == SOCKET_ERROR )
{
TRACE(_T("Server Socket Listen Failed"));
closesocket(sk);
return FALSE;
}
WSAEVENT wsaEvent = WSACreateEvent();
if (wsaEvent == INVALID_HANDLE_VALUE)
{
closesocket(sk);
TRACE(_T("CreateEvent Failed"));
return FALSE;
}
if (WSAEventSelect(sk, wsaEvent, FD_ACCEPT|FD_CLOSE) != 0)
{
TRACE(_T("WSAEventSelect Failed"));
closesocket(sk);
CloseHandle(wsaEvent);
return FALSE;
}
DWORD dwThreadID;
m_hWkThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WkThread, this, 0, &dwThreadID);
if (m_hWkThread == INVALID_HANDLE_VALUE)
{
TRACE(_T("WSAEventSelect Failed"));
closesocket(sk);
CloseHandle(wsaEvent);
return FALSE;
}
m_EventArray[m_nEventTotal] = wsaEvent;
m_SockArray[m_nEventTotal] = sk;
++m_nEventTotal;
return TRUE;
}
DWORD WINAPI CEventSocket::WkThread(LPVOID lParam)
{
CEventSocket * pThis = reinterpret_cast<CEventSocket *>(lParam);
ASSERT(NULL != pThis);
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == INVALID_HANDLE_VALUE)
{
pThis->m_hWkThread = NULL;
return 2;
}
pThis->m_hStopEvent = hEvent;
while (WaitForSingleObject(hEvent, 0) == WSA_WAIT_TIMEOUT)
{
int nIndex = ::WSAWaitForMultipleEvents(pThis->m_nEventTotal, pThis->m_EventArray,
FALSE, 500, FALSE);
if (nIndex == WSA_WAIT_TIMEOUT)
continue;
if (nIndex != WSA_WAIT_FAILED)
{
nIndex -= WSA_WAIT_EVENT_0;
WSANETWORKEVENTS netEvent;
WSAEnumNetworkEvents(pThis->m_SockArray[nIndex], pThis->m_EventArray[nIndex], &netEvent);
WSAResetEvent(pThis->m_EventArray[nIndex]);
if (netEvent.lNetworkEvents&FD_ACCEPT && netEvent.iErrorCode[FD_ACCEPT_BIT] == 0)
{
if (pThis->m_nEventTotal >= MAX_WSAEVENT_NUMS)
{
TRACE(_T("Too many Events"));
continue;
}
SOCKET sk = accept(pThis->m_SockArray[nIndex], NULL, NULL);
sockaddr_in skAddr = {0};
int addrLen = sizeof(sockaddr_in);
::getsockname (sk,(sockaddr*)&skAddr,&addrLen);
UINT64 fromAddr = (UINT64) skAddr.sin_addr.S_un.S_addr << 32 | ntohs(skAddr.sin_port);
pThis->m_ClientList[fromAddr] = pThis->m_nEventTotal;
WSAEVENT wsaEvent = WSACreateEvent();
WSAEventSelect(sk, wsaEvent, FD_READ|FD_WRITE|FD_CLOSE);
pThis->m_EventArray[pThis->m_nEventTotal] = wsaEvent;
pThis->m_SockArray[pThis->m_nEventTotal] = sk;
++pThis->m_nEventTotal;
}
else if (netEvent.lNetworkEvents&FD_READ && netEvent.iErrorCode[FD_READ_BIT] == 0)
{
char buffer[2048] = {0};
int nDataSize = recv(pThis->m_SockArray[nIndex], buffer, 2048, 0);
sockaddr_in skAddr = {0};
int addrLen = sizeof(sockaddr_in);
::getsockname (pThis->m_SockArray[nIndex],(sockaddr*)&skAddr,&addrLen);
UINT64 fromAddr = (UINT64) skAddr.sin_addr.S_un.S_addr << 32 | ntohs(skAddr.sin_port);
//pThis->RecvDataNotidy(fromAddr, buffer+12, nDataSize-12);
pThis->RecvDataNotidy(fromAddr, buffer, nDataSize);
}
else if (netEvent.lNetworkEvents&FD_CLOSE && netEvent.iErrorCode[FD_CLOSE_BIT] == 0)
{
sockaddr_in skAddr = {0};
int addrLen = sizeof(sockaddr_in);
::getsockname (pThis->m_SockArray[nIndex],(sockaddr*)&skAddr,&addrLen);
UINT64 fromAddr = (UINT64) skAddr.sin_addr.S_un.S_addr << 32 | ntohs(skAddr.sin_port);
pThis->CloseNotidy(fromAddr);
closesocket(pThis->m_SockArray[nIndex]);
WSACloseEvent(pThis->m_EventArray[nIndex]);
for (int i = nIndex; i < pThis->m_nEventTotal; i++)
{
pThis->m_SockArray[i] = pThis->m_SockArray[i+1];
pThis->m_EventArray[i] = pThis->m_EventArray[i+1];
}
pThis->m_SockArray[pThis->m_nEventTotal] = NULL;
pThis->m_EventArray[pThis->m_nEventTotal] = NULL;
-- pThis->m_nEventTotal;
map<UINT64, int>::iterator iterIdx = pThis->m_ClientList.find(fromAddr);
if (iterIdx != pThis->m_ClientList.end())
pThis->m_ClientList.erase(iterIdx);
}
}
}
CloseHandle(hEvent);
pThis->m_hStopEvent = NULL;
return 0;
}
void CEventSocket::StopListen()
{
if (m_hWkThread == INVALID_HANDLE_VALUE)
return;
SetEvent(m_hStopEvent);
::WaitForSingleObject(m_hWkThread, INFINITE);
m_hWkThread = NULL;
for (int i = 0; i < m_nEventTotal; i++)
{
closesocket(m_SockArray[i]);
m_SockArray[i] = NULL;
WSACloseEvent(m_EventArray[i]);
m_EventArray[i] = NULL;
}
m_ClientList.clear();
}
int CEventSocket::SendData(UINT64 toAddr, char *pData, int nDataSize)
{
map<UINT64, int>::iterator iterIdx = m_ClientList.find(toAddr);
if (iterIdx != m_ClientList.end() && m_SockArray[iterIdx->second] != NULL)
{
return send(m_SockArray[iterIdx->second], pData, nDataSize, 0);
}
return -1;
}
#pragma once
#include <map>
using namespace std;
#define MAX_PENDING_CONNECTIONS 20
#define MAX_WSAEVENT_NUMS 64
class CEventSocket
{
public:
CEventSocket(void);
virtual ~CEventSocket(void);
virtual void RecvDataNotidy(UINT64 fromAddr, char *pData, int nDataSize) {}
virtual void CloseNotidy(UINT64 fromAddr) {}
BOOL ListenOn(int port, int sockType = SOCK_STREAM, int protocol = IPPROTO_TCP);
void StopListen();
int SendData(UINT64 toAddr, char *pData, int nDataSize);
protected:
static DWORD WINAPI WkThread(LPVOID lParam);
private:
int m_nEventTotal;
HANDLE m_hWkThread;
HANDLE m_hStopEvent;
map<UINT64, int> m_ClientList;
WSAEVENT m_EventArray[MAX_WSAEVENT_NUMS];
SOCKET m_SockArray[MAX_WSAEVENT_NUMS];
};
实现文件
posted on 2008-12-19 15:56
黑色天使 阅读(2225)
评论(2) 编辑 收藏 引用 所属分类:
网络开发