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

这是以前仿照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;
}

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值