//EventSocket.h //from sizhizheng.blogchina.com
#pragma once
#include
#define STOP 0
#define RUN 1
#define PAUSE 2
#define MaxState PAUSE
class CEventSocket //from sizhizheng.blogchina.com
{
protected:
int sAf,sType,sProtocol,sPort; //socket协议族,类型,协议 ,监听端口
UINT statConn; //连接状态
long sNetworkEvents; //关联事件
SOCKET m_SocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT m_EventArr[MAXIMUM_WAIT_OBJECTS];
CRITICAL_SECTION csSockArr; //socket数组访问临界区
public:
int m_iTotalConn; //socket计数
CEventSocket(void);
~CEventSocket(void);
static bool __stdcall EventSocketInit(WSADATA* lpwsaData = NULL);
static DWORD WINAPI WorkThread(LPVOID lpObject);//工作线程
protected: //处理接口
virtual void OnReceive(int nNum,int /*nErrorCode*/);
virtual void OnSend(int nNum,int /*nErrorCode*/);
virtual void OnOutOfBandData(int nNum,int /*nErrorCode*/);
virtual void OnAccept(int nNum,int /*nErrorCode*/);
virtual void OnConnect(int nNum,int /*nErrorCode*/);
virtual void OnClose(int nNum,int /*nErrorCode*/);
public:
virtual bool Create(int af,int type,int protocol,long NetworkEvents);
virtual bool NewSocket(SOCKET s=INVALID_SOCKET); //添加套接字
virtual bool NewLisSock(int nPort,int nConnectionBacklog=5); //添加监听监听套接字
bool Listen(int nNum=0,int nConnectionBacklog=5);
virtual SOCKET Accept(int nNum=0,SOCKADDR* lpSockAddr=NULL, int* nSockAddrLen=NULL);
bool Bind(UINT nSocketPort, LPSTR lpszSocketAddress = NULL,int nNum=0);
bool Bind (int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen);
bool Connect(int nNum,LPSTR lpszHostAddress, UINT nHostPort);
bool Connect(int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen);
virtual int Send(int nNum,const void* lpBuf, int nBufLen, int nFlags=0);
int SendTo(int nNum,const void* lpBuf, int nBufLen,
UINT nHostPort, LPSTR lpszHostAddress = NULL, int nFlags = 0);
int SendTo(int nNum,const void* lpBuf, int nBufLen,
const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags = 0);
virtual int Receive(int nNum,void* lpBuf, int nBufLen, int nFlags=0);
int ReceiveFrom(int nNum,void* lpBuf, int nBufLen,
char* rSocketAddress, UINT& rSocketPort, int nFlags = 0);
int ReceiveFrom(int nNum,void* lpBuf, int nBufLen,
SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags = 0);
bool GetPeerName(int nNum,CString& rPeerAddress, UINT& rPeerPort);
bool GetPeerName(int nNum,SOCKADDR* lpSockAddr, int* lpSockAddrLen);
bool GetSockName(int nNum,CString& rSocketAddress, UINT& rSocketPort);
bool GetSockName(int nNum,SOCKADDR* lpSockAddr, int* lpSockAddrLen);
bool SetSockOpt(int nNum,int nOptionName, const void* lpOptionValue,
int nOptionLen, int nLevel = SOL_SOCKET);
bool GetSockOpt(int nNum,int nOptionName, void* lpOptionValue,
int* lpOptionLen, int nLevel = SOL_SOCKET);
bool EventSelect(int nNum,long Events=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
int ShutDown(int nNum,int nHow);
virtual int Close(int nNum);
virtual void KillSocket(int nNum);
public:
bool SetState(UINT state);
UINT GetState(void);
static int PASCAL GetLastError();
protected:
virtual int SendToHelper(int nNum,const void* lpBuf, int nBufLen,
const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags);
virtual int ReceiveFromHelper(int nNum,void* lpBuf, int nBufLen,
SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags);
virtual bool ConnectHelper(int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen
};
inline int CEventSocket::ShutDown(int nNum,int nHow)
{return shutdown(m_SocketArr[nNum],nHow);
}
inline bool CEventSocket::Bind(int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen)
{ return (SOCKET_ERROR != bind(m_SocketArr[nNum], lpSockAddr, nSockAddrLen)); }
inline int CEventSocket::SendTo(int nNum,const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags)
{ return SendToHelper(nNum,lpBuf, nBufLen, lpSockAddr, nSockAddrLen, nFlags); }
inline int CEventSocket::ReceiveFrom(int nNum,void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags)
{ return ReceiveFromHelper(nNum,lpBuf, nBufLen, lpSockAddr, lpSockAddrLen, nFlags); }
inline bool CEventSocket::Listen(int nNum,int nConnectionBacklog)
{ return (SOCKET_ERROR != listen(m_SocketArr[nNum], nConnectionBacklog)); }
inline bool CEventSocket::Connect(int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen)
{ return ConnectHelper(nNum,lpSockAddr, nSockAddrLen); }
inline int PASCAL CEventSocket::GetLastError()
{ return WSAGetLastError(); }
inline bool CEventSocket::GetPeerName(int nNum,SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{ return (SOCKET_ERROR != getpeername(m_SocketArr[nNum], lpSockAddr, lpSockAddrLen)); }
inline bool CEventSocket::GetSockName(int nNum,SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{ return (SOCKET_ERROR != getsockname(m_SocketArr[nNum], lpSockAddr, lpSockAddrLen)); }
inline bool CEventSocket::SetSockOpt(int nNum,int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel)
{ return (SOCKET_ERROR != setsockopt(m_SocketArr[nNum], nLevel, nOptionName, (LPCSTR)lpOptionValue, nOptionLen)); }
inline bool CEventSocket::GetSockOpt(int nNum,int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel)
{ return (SOCKET_ERROR != getsockopt(m_SocketArr[nNum], nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen)); }
//EventSocket.cpp //from sizhizheng.blogchina.com
#include "stdafx.h"
#include
#include "EventSocket.h"
#include
#include
//from sizhizheng.blogchina.com
#pragma comment(lib, "ws2_32.lib")
bool __stdcall CEventSocket::EventSocketInit(WSADATA* lpwsaData)
{
WSADATA wsaData;
if (lpwsaData == NULL)
lpwsaData = &wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int nResult = WSAStartup(wVersionRequested, lpwsaData);
if (nResult != 0)
return FALSE;
if (LOBYTE(lpwsaData->wVersion) != 1 || HIBYTE(lpwsaData->wVersion) != 1)
{
WSACleanup();
return FALSE;
}
return TRUE;
}
CEventSocket::CEventSocket(void)
{
m_iTotalConn = 0;
SetState(RUN);
memset(m_SocketArr,INVALID_SOCKET,sizeof(SOCKET)*MAXIMUM_WAIT_OBJECTS);
memset(m_EventArr,0,sizeof(WSAEVENT)*MAXIMUM_WAIT_OBJECTS);
InitializeCriticalSection(&csSockArr);
}
bool CEventSocket::Create(int af,int type,int protocol,long NetworkEvents)
{
sProtocol = protocol;
sType = type;
sAf = af;
sNetworkEvents=NetworkEvents;
CreateThread(NULL, 0,WorkThread,this, 0, NULL);
return true;
}
CEventSocket::~CEventSocket(void)
{
int i=0;
while(m_EventArr[i]!=0 &&i<=MAXIMUM_WAIT_OBJECTS)
{
WSACloseEvent(m_EventArr[i++]);
}
DeleteCriticalSection(&csSockArr);
SetState(STOP);
}
DWORD WINAPI CEventSocket::WorkThread(LPVOID lpObject)
{
int ret, index,nErrorCode;
WSANETWORKEVENTS NetworkEvents;
CEventSocket *EventSock=(CEventSocket*) lpObject;
while (EventSock->statConn!=STOP)
{
ret = WSAWaitForMultipleEvents(EventSock->m_iTotalConn, EventSock->m_EventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(EventSock->m_SocketArr[index], EventSock->m_EventArr[index], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
{
nErrorCode=NetworkEvents.iErrorCode[FD_READ_BIT];
EventSock->OnReceive(index,nErrorCode);
}
if (NetworkEvents.lNetworkEvents & FD_WRITE)
{
nErrorCode=NetworkEvents.iErrorCode[FD_WRITE_BIT];
EventSock->OnSend(index,nErrorCode);
}
if (NetworkEvents.lNetworkEvents & FD_OOB)
{
nErrorCode=NetworkEvents.iErrorCode[FD_OOB_BIT];
EventSock->OnOutOfBandData(index,nErrorCode);
}
if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
{
nErrorCode=NetworkEvents.iErrorCode[FD_ACCEPT_BIT];
EventSock->OnAccept(index,nErrorCode);
}
if (NetworkEvents.lNetworkEvents & FD_CONNECT)
{
nErrorCode=NetworkEvents.iErrorCode[FD_CONNECT_BIT];
EventSock->OnConnect(index,nErrorCode);
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
nErrorCode=NetworkEvents.iErrorCode[FD_CLOSE_BIT];
EventSock->OnClose(index,nErrorCode);
}
if(EventSock->statConn==PAUSE)
Sleep(1000);
}
return 0;
}
void CEventSocket::OnReceive(int nNum,int /*nErrorCode*/)
{
}
void CEventSocket::OnSend(int nNum,int /*nErrorCode*/)
{
}
void CEventSocket::OnOutOfBandData(int nNum,int /*nErrorCode*/)
{
}
void CEventSocket::OnAccept(int nNum,int /*nErrorCode*/)
{
}
void CEventSocket::OnConnect(int nNum,int /*nErrorCode*/)
{
}
void CEventSocket::OnClose(int nNum,int /*nErrorCode*/)
{
}
bool CEventSocket::NewSocket(SOCKET s)
{
EnterCriticalSection(&csSockArr);
if (m_SocketArr[m_iTotalConn] != INVALID_SOCKET || m_iTotalConn>=MAXIMUM_WAIT_OBJECTS)
{
LeaveCriticalSection(&csSockArr);
return false;
}
if (s==INVALID_SOCKET)
{
m_SocketArr[m_iTotalConn]=socket(sAf,sType,sProtocol);
}else {
m_SocketArr[m_iTotalConn]=s;
}
if(m_EventArr[m_iTotalConn]==0)
{
m_EventArr[m_iTotalConn]=WSACreateEvent();
}
EventSelect(m_iTotalConn,sNetworkEvents);
m_iTotalConn++;
LeaveCriticalSection(&csSockArr);
return true;
}
bool CEventSocket::NewLisSock(int nPort,int nConnectionBacklog)
{
bool ret=true;
if (0==nPort)
SetLastError(WSAEINVAL);
ret&=NewSocket();
ret&=EventSelect(m_iTotalConn-1,FD_ACCEPT|FD_CLOSE);
ret&=Bind(nPort);
ret&=Listen(m_iTotalConn-1, nConnectionBacklog);
return ret;
};
SOCKET CEventSocket::Accept(int nNum,SOCKADDR* lpSockAddr, int* nSockAddrLen)
{
return accept(m_SocketArr[nNum],lpSockAddr,nSockAddrLen);
}
bool CEventSocket::Bind(UINT nSocketPort, LPSTR lpszSocketAddress,int nNum)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
if (lpszSocketAddress == NULL)
{
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
DWORD lResult = inet_addr(lpszSocketAddress);
if (lResult == INADDR_NONE)
{
WSASetLastError(WSAEINVAL);
return FALSE;
}
sockAddr.sin_addr.s_addr = lResult;
}
sockAddr.sin_port = htons((u_short)nSocketPort);
return Bind(nNum,(SOCKADDR*)&sockAddr, sizeof(sockAddr));
}
bool CEventSocket::Connect(int nNum,LPSTR lpszHostAddress, UINT nHostPort)
{
if (lpszHostAddress == NULL)
{
return FALSE;
}
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszHostAddress);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
return FALSE;
}
}
sockAddr.sin_port = htons((u_short)nHostPort);
return Connect(nNum,(SOCKADDR*)&sockAddr, sizeof(sockAddr));
}
bool CEventSocket::ConnectHelper(int nNum,const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
return connect(m_SocketArr[nNum], lpSockAddr, nSockAddrLen) != SOCKET_ERROR;
}
int CEventSocket::Send(int nNum,const void* lpBuf, int nBufLen, int nFlags)
{
return send(m_SocketArr[nNum], (LPSTR)lpBuf, nBufLen, nFlags);
}
int CEventSocket::Receive(int nNum,void* lpBuf, int nBufLen, int nFlags)
{
return recv(m_SocketArr[nNum], (LPSTR)lpBuf, nBufLen, nFlags);
}
int CEventSocket::SendTo(int nNum,const void* lpBuf, int nBufLen, UINT nHostPort, LPSTR lpszHostAddress, int nFlags)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
if (lpszHostAddress == NULL)
sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
else
{
sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszHostAddress);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
}
}
sockAddr.sin_port = htons((u_short)nHostPort);
return SendTo(nNum,lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);
}
int CEventSocket::SendToHelper(int nNum,const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags)
{
return sendto(m_SocketArr[nNum], (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, nSockAddrLen);
}
int CEventSocket::ReceiveFrom(int nNum,void* lpBuf, int nBufLen, char* rSocketAddress, UINT& rSocketPort, int nFlags)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int nSockAddrLen = sizeof(sockAddr);
int nResult = ReceiveFrom(nNum,lpBuf, nBufLen, (SOCKADDR*)&sockAddr, &nSockAddrLen, nFlags);
if(nResult != SOCKET_ERROR)
{
rSocketPort = ntohs(sockAddr.sin_port);
rSocketAddress = inet_ntoa(sockAddr.sin_addr);
}
return nResult;
}
int CEventSocket::ReceiveFromHelper(int nNum,void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags)
{
return recvfrom(m_SocketArr[nNum], (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, lpSockAddrLen);
}
int CEventSocket::Close(int nNum)
{
if (m_SocketArr[nNum]!=INVALID_SOCKET)
{
int ret=closesocket(m_SocketArr[nNum]);
KillSocket(nNum);
return ret;
}else{
return WSAENOTSOCK;
}
}
void CEventSocket::KillSocket(int nNum)
{
EnterCriticalSection(&csSockArr);
m_iTotalConn--;
m_SocketArr[nNum]=m_SocketArr[m_iTotalConn];
EventSelect(nNum,sNetworkEvents);
m_SocketArr[m_iTotalConn]=INVALID_SOCKET;
LeaveCriticalSection(&csSockArr);
}
bool CEventSocket::GetPeerName(int nNum,CString& rPeerAddress, UINT& rPeerPort)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int nSockAddrLen = sizeof(sockAddr);
bool bResult = GetPeerName(nNum,(SOCKADDR*)&sockAddr, &nSockAddrLen);
if (bResult)
{
rPeerPort = ntohs(sockAddr.sin_port);
rPeerAddress = inet_ntoa(sockAddr.sin_addr);
}
return bResult;
}
bool CEventSocket::GetSockName(int nNum,CString& rSocketAddress, UINT& rSocketPort)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int nSockAddrLen = sizeof(sockAddr);
bool bResult = GetSockName(nNum,(SOCKADDR*)&sockAddr, &nSockAddrLen);
if (bResult)
{
rSocketPort = ntohs(sockAddr.sin_port);
rSocketAddress = inet_ntoa(sockAddr.sin_addr);
}
return bResult;
}
bool CEventSocket::EventSelect(int nNum,long Events)
{
if(m_SocketArr[nNum] == INVALID_SOCKET)
{
WSASetLastError(WSAENOTSOCK);
return false;
}
return WSAEventSelect(m_SocketArr[nNum],m_EventArr[nNum], Events) != SOCKET_ERROR;
}
bool CEventSocket::SetState(UINT state)
{
if (state {
statConn=state;
return true;
}
return false;
}
UINT CEventSocket::GetState(void)
{
return statConn;
}