您的位置:首页 > 其它

一个基于事件模型的socket封装类CEventSocket

2007-03-31 13:20 369 查看
这是以前仿照MFC中的CAsyncSocket类写的一个基于事件模型的封装类~用法跟CAsyncSocket差不多,派生并重写接口.不同的是,这里会生成一个新的工作线程并在最大64个socket上进行操作.不过有些地方感觉还是不完善(比如错误代码处理上面还有其他什么不知道的地方),也不知道有没有必要写文档.贴出来大家看看有什么需要改进的,谢谢留言~(目前只测试了tcp连接的,可以正常工作)
//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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: