自己封装socket(更新啦)

来源:互联网 发布:python迭代器和生成器 编辑:程序博客网 时间:2024/06/05 07:36

CAsynSocket似乎总难满足要求,不能跨线程使用应该是它的致命伤,直接使用socket是最好的办法,这也是许多大牛们推荐的方法。为了避免重复劳动,自己封装了一个CMySocket类,希望能像CAsynSocket一样使用(现在还不可能了,偶也是初学,只有慢慢完善,也许有一天能接近CAsynSocket ),既然是自己封装的类,是否线程安全就自己说了算了,呵呵。

目前实现如下功能:

创建socket、数据收发(TCP和UDP)、收发缓冲区大小设置等。

IO模型采用WSAEventSelect机制。

 用它实现了局域网的聊天程序,挺好用。如有不恰当的地方,请给我留言,我会将其逐步完善!

使用方法:

继承CMySocket类,重载OnAccept、OnReceive等函数(和CAsyncSocket方法相同)。不用调用AfxSocketInit函数,因为该函数所作工作在我封装的代码中已完成。

 

 下面是代码

******************************头文件 MySocket.h***********************

 
#ifndef   __MYSOCKET_H__
#define   __MYSOCKET_H__

#include <WINSOCK2.H>

#define  MAX_SOCKET    64

#pragma comment(lib,"Ws2_32.lib")

typedef struct tagClient
{
 sockaddr addr;
 SOCKET sock;
}TClient;

class CMySocket
{
public:
 CMySocket();
 CMySocket(const CMySocket&);
 ~CMySocket();

 static int StartUp();
 int Create(int port,int socket_type,long lEvent=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
 int Close();
 int Listen(int backlog=SOMAXCONN);
 int Accept(CMySocket* pSocket,struct sockaddr* addr);
 int Connect(const char* IP,int port);
 int Receive(char* buf,int len);
 int Receive(char* buf,int len,char* IP,int* port);
 int Send(char* buf,int len);
 int Send(char* buf,int len,const char* IP,int port);
 int GetRcvBufSize(int* bufsize,int* len);
 int GetSndBufSize(int* bufsize,int* len);
 int SetRcvBufSize(int* bufsize,int len);
 int SetSndBufSize(int* bufsize,int len);
 CMySocket operator = (CMySocket& mySocket1);

 virtual void OnAccept(int errorcode);
 virtual void OnConnect(int errorcode);
 virtual void OnReceive(int errorcode);
 virtual void OnSend(int errorcode);
 virtual void OnClose(int errorcode);

 static void GetSocketAddr(struct sockaddr* addr);
 static void RemoveSocket(SOCKET s);
 
 SOCKET m_socket;
 int    m_nSocketType;
 long   m_lEvent;
 BOOL   m_bThreadStarted;
 BOOL   m_bEndTread;

 static int m_nClientNum;
 static TClient clientList[MAX_SOCKET];
 static SOCKET socketArray[MAX_SOCKET];
 static WSAEVENT eventArrray[MAX_SOCKET];
 static int m_totalSocket;
 static DWORD m_dwIndex;
 static CRITICAL_SECTION m_cs;

protected:
 static int m_nInstnum;
 static BOOL m_bStartUp;
 static BOOL m_bInitCS;
private:
};


#endif

 


***************************代码实现 MySocket.cpp*****************************

#include "stdafx.h"
#include "MySocket.h"

#include <process.h>

void SocketThread(void* parm);

TClient          CMySocket::clientList[MAX_SOCKET];
SOCKET       CMySocket::socketArray[MAX_SOCKET];
WSAEVENT      CMySocket::eventArrray[MAX_SOCKET];
int        CMySocket::m_totalSocket = 0;
int     CMySocket::m_nInstnum = 0;
int     CMySocket::m_nClientNum = 0;
DWORD       CMySocket::m_dwIndex = 0;
BOOL       CMySocket::m_bStartUp = FALSE;
BOOL       CMySocket::m_bInitCS = FALSE;
CRITICAL_SECTION CMySocket::m_cs;

CMySocket::CMySocket()
{
 m_socket = INVALID_SOCKET;
 m_bThreadStarted = FALSE;
 m_bEndTread = FALSE;
 m_nInstnum++;
 if (!m_bInitCS)
 {
  InitializeCriticalSection(&m_cs);
  m_bInitCS = TRUE;
 }
}

CMySocket::CMySocket(const CMySocket& myScoket)
{
 m_socket = myScoket.m_socket;
 m_nSocketType = myScoket.m_nSocketType;
}

CMySocket::~CMySocket()
{
 m_nInstnum--;
 if (m_socket != INVALID_SOCKET)
 {
  closesocket(m_socket);
 }
 if (!m_nInstnum)
 {
  WSACleanup();
  m_bStartUp = FALSE;
 }
}

int CMySocket::StartUp()
{
 if (!m_bStartUp)
 {
  WSADATA wsaData;
  if (WSAStartup(WINSOCK_VERSION,&wsaData))
  {
   int err = WSAGetLastError();
   return err;
  }
 }
 return 0;
}

int CMySocket::Create(int port,int socket_type,long lEvent)
{
 if (!m_bStartUp)
 {
  StartUp();
 }
 if (m_socket != INVALID_SOCKET)
 {
  return 0;
 }
 m_nSocketType = socket_type;
 m_socket = socket(AF_INET,m_nSocketType,0);
 if (m_socket == INVALID_SOCKET)
 {
  int err = WSAGetLastError();
  return err;
 }
 else
 {
  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.S_un.S_addr = INADDR_ANY;
  addr.sin_port = htons(port);
  if (bind(m_socket,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
 }

 WSAEVENT wsaEvent = WSACreateEvent();
 if (WSAEventSelect(m_socket,wsaEvent,lEvent))
 {
   int err = WSAGetLastError();
   return err;
 }

 EnterCriticalSection(&m_cs);
 socketArray[m_totalSocket] = m_socket;
 eventArrray[m_totalSocket] = wsaEvent;
 m_totalSocket++;
 LeaveCriticalSection(&m_cs);

 m_bEndTread = FALSE;
 if (_beginthread(SocketThread,0,this) == -1)
 {
  return -1;
 }
 int loopnum = 0;
 while (!m_bThreadStarted)
 {
  loopnum++;
  if (loopnum > 200)
  {
   return -1;
  }
  Sleep(10);
 }

 return 0;
}

int CMySocket::Close()
{
 RemoveSocket(m_socket);
 if (closesocket(m_socket) == SOCKET_ERROR)
 {
  int err = WSAGetLastError();
  return err;
 }
 m_socket = INVALID_SOCKET;
 m_bEndTread = TRUE;

 
 return 0;
}

int CMySocket::Listen(int backlog)
{
 if (listen(m_socket,backlog) == SOCKET_ERROR)
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

int CMySocket::Accept(CMySocket* pSocket,struct sockaddr* addr)
{
 SOCKET sock;
 int len = sizeof(struct sockaddr);
 if ((sock = accept(m_socket,addr,&len)) == INVALID_SOCKET)
 {
  int err = WSAGetLastError();
  return err;
 }
 pSocket->m_socket = sock;
 pSocket->m_nSocketType = SOCK_STREAM;

 WSAEVENT wsaEvent = WSACreateEvent();
 if (WSAEventSelect(sock,wsaEvent,FD_READ | FD_CLOSE))
 {
   int err = WSAGetLastError();
   return err;
 }
 
 EnterCriticalSection(&m_cs);
 
 socketArray[m_totalSocket] = sock;
 eventArrray[m_totalSocket] = wsaEvent;
 m_totalSocket++;

 int index = m_nClientNum;
 clientList[index].addr = *addr;
 clientList[index].sock = sock;
 m_nClientNum++;

 LeaveCriticalSection(&m_cs);
 
 return 0;
}

int CMySocket::Connect(const char* IP,int port)
{
 sockaddr_in addr;
 addr.sin_family = AF_INET;
 addr.sin_addr.S_un.S_addr = inet_addr(IP);
 addr.sin_port = htons(port);

 if (connect(m_socket,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

void CMySocket::RemoveSocket(SOCKET s)
{
 int i,j;

 EnterCriticalSection(&m_cs);
 
 int totalSocket = m_totalSocket;
 for (i=0;i<totalSocket;i++)
 {
  if (CMySocket::socketArray[i] == s)
  {
   for (j=i;j<totalSocket-1;j++)
   {
    socketArray[j] = socketArray[j+1];
    eventArrray[j] = eventArrray[j+1];
   }
   m_totalSocket--;
   break;
  }
 }
 
 int num = m_nClientNum;
 for (i=0;i<num;i++)
 {
  if (clientList[i].sock == s)
  {
   for (j=i;j<num-1;j++)
   {
    clientList[j].sock = clientList[j+1].sock;
    clientList[j].addr = clientList[j+1].addr;
   }
   m_nClientNum--;
   break;
  }
 }
 
 LeaveCriticalSection(&m_cs);
}

void SocketThread(void* parm)
{
 CMySocket *pMySocket = (CMySocket*)parm;

 WSANETWORKEVENTS tEvent;
 DWORD ret;
 DWORD dwIndex;
 int errorcode;
 int timeout = 10;
 pMySocket->m_bThreadStarted = TRUE;
 while (1)
 {
  EnterCriticalSection(&CMySocket::m_cs);
  ret = WSAWaitForMultipleEvents(CMySocket::m_totalSocket,CMySocket::eventArrray,FALSE,timeout,FALSE);
  LeaveCriticalSection(&CMySocket::m_cs);

  if (pMySocket->m_bEndTread)
  {
   _endthread();
  }
  if (ret == WSA_WAIT_TIMEOUT)
  {
   continue;
  }
  dwIndex = ret;
  
  dwIndex -= WSA_WAIT_EVENT_0;
  CMySocket::m_dwIndex = dwIndex;

  memset(&tEvent,0,sizeof(WSANETWORKEVENTS));
  EnterCriticalSection(&CMySocket::m_cs);
  WSAEnumNetworkEvents(CMySocket::socketArray[dwIndex],CMySocket::eventArrray[dwIndex],&tEvent);
  WSAResetEvent(CMySocket::eventArrray[dwIndex]);
  LeaveCriticalSection(&CMySocket::m_cs);
  
  if (tEvent.lNetworkEvents & FD_CONNECT)
  {
   errorcode = tEvent.iErrorCode[FD_CONNECT_BIT];
   pMySocket->OnConnect(errorcode);
  }
  else if (tEvent.lNetworkEvents & FD_ACCEPT)
  {
   errorcode = tEvent.iErrorCode[FD_ACCEPT_BIT];
   pMySocket->OnAccept(errorcode);
  }
  else if (tEvent.lNetworkEvents & FD_READ)
  {
   DWORD nBytes = 0;
   errorcode = tEvent.iErrorCode[FD_READ_BIT];
   ioctlsocket(CMySocket::socketArray[dwIndex],FIONREAD,&nBytes);
   if (nBytes > 0)
    pMySocket->OnReceive(errorcode);
  }
  else if (tEvent.lNetworkEvents & FD_WRITE)
  {
   errorcode = tEvent.iErrorCode[FD_WRITE_BIT];
   pMySocket->OnSend(errorcode);
  }
  else if (tEvent.lNetworkEvents & FD_CLOSE)
  {
   errorcode = tEvent.iErrorCode[FD_CLOSE_BIT];
   pMySocket->OnClose(errorcode);
   CMySocket::RemoveSocket(CMySocket::socketArray[dwIndex]);
  }
  else
  {
  }
 }
}

int CMySocket::Receive(char* buf,int len)
{
 sockaddr addr;
 int size = sizeof(addr);

 switch(m_nSocketType)
 {
 case SOCK_DGRAM:
  if (recvfrom(m_socket,buf,len,0,&addr,&size) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  break;
 case SOCK_STREAM:
  if (recv(m_socket,buf,len,0) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  break;
 default:
  break;
 }

 return 0;
}

int CMySocket::Receive(char* buf,int len,char* IP,int* port)
{
 sockaddr addr;
 int size = sizeof(addr);
 sockaddr_in* pAddr_in;

 switch(m_nSocketType)
 {
 case SOCK_DGRAM:
  if (recvfrom(m_socket,buf,len,0,&addr,&size) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  pAddr_in = (sockaddr_in*)&addr;
  strcpy(IP,inet_ntoa(pAddr_in->sin_addr));
  *port = ntohs(pAddr_in->sin_port);
  break;
 case SOCK_STREAM:
  if (recv(m_socket,buf,len,0) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  break;
 default:
  break;
 }
 
 return 0;
}

int CMySocket::Send(char* buf,int len)
{
 if (send(m_socket,buf,len,0) == SOCKET_ERROR)
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

int CMySocket::Send(char* buf,int len,const char* IP,int port)
{
 sockaddr_in addr;
 addr.sin_family = AF_INET;
 addr.sin_addr.S_un.S_addr = inet_addr(IP);
 addr.sin_port = htons(port);

 switch(m_nSocketType)
 {
 case SOCK_DGRAM:
  if (sendto(m_socket,buf,len,0,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  break;
 case SOCK_STREAM:
  if (send(m_socket,buf,len,0) == SOCKET_ERROR)
  {
   int err = WSAGetLastError();
   return err;
  }
  break;
 default:
  break;
 }
 
 return 0;
}

int CMySocket::GetRcvBufSize(int* bufsize,int* len)
{
 if (getsockopt(m_socket,SOL_SOCKET,SO_RCVBUF,(char*)bufsize,len))
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

int CMySocket::GetSndBufSize(int* bufsize,int* len)
{
 if (getsockopt(m_socket,SOL_SOCKET,SO_SNDBUF,(char*)bufsize,len))
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

int CMySocket::SetRcvBufSize(int* bufsize,int len)
{
 if (setsockopt(m_socket,SOL_SOCKET,SO_RCVBUF,(char*)bufsize,len))
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

int CMySocket::SetSndBufSize(int* bufsize,int len)
{
 if (setsockopt(m_socket,SOL_SOCKET,SO_SNDBUF,(char*)bufsize,len))
 {
  int err = WSAGetLastError();
  return err;
 }
 return 0;
}

CMySocket CMySocket::operator = (CMySocket& mySocket1)
{
 CMySocket newScoket;

 newScoket.m_socket = mySocket1.m_socket;
 newScoket.m_nSocketType = mySocket1.m_nSocketType;
 
 return newScoket;
}

void CMySocket::GetSocketAddr(struct sockaddr* addr)
{
 EnterCriticalSection(&m_cs);

 int num = m_nClientNum;
 for (int i=0;i<num;i++)
 {
  if (clientList[i].sock == socketArray[m_dwIndex])
  {
   *addr = clientList[i].addr;
   LeaveCriticalSection(&m_cs);
   return;
  }
 }
 addr->sa_data[0] = 0;

 LeaveCriticalSection(&m_cs);
}

void CMySocket::OnReceive(int errorcode)
{
}

void CMySocket::OnAccept(int errorcode)
{
}

void CMySocket::OnClose(int errorcode)
{
}

void CMySocket::OnConnect(int errorcode)
{
}

void CMySocket::OnSend(int errorcode)
{
}


原创粉丝点击