socket cp2

-------------cpio.h

#pragma once
#include "SocketPool.h"
#include <list>
#include <afxmt.h>
#include "dll.h"

extern IOCP_API int  g_running;
class IOCP_API CIOCP
{
public:
 CIOCP(void);
 virtual ~CIOCP(void);
public:

 // 开始服务,port 为监听的TCP端口号,工作于TCP监听状态,其他方法请重写start方法
 int Start(int port, int maxConnection);

 // 停止服务
 int Stop(void);

 //处理IOCP上的消息
 int ProcessIOCPMessage(ClientSocket* pClinetSocket, OVERLAPPEDEX* pOlex);

 //工作线程处理逻辑
 int WorkerThreadLogic(void);

 //写数据
 int WriteMessage(ClientSocket* pClinetSocket, BYTE* msg, int len,
              const BOOL bSaveSend = TRUE);

 //向一个UDP地址发送数据
 int WriteMessageTo(ClientSocket* pClinetSocket, BYTE* msg, int len, sockaddr_in& addrTo,
  const BOOL bSaveSend = TRUE);

 //受到数据
 virtual int RecvMessage(ClientSocket* pClinetSocket) = 0;


 //新收到一个连接
 virtual int NotifyNewConnect(ClientSocket* pClientSocket) = 0;

 //断开一个连接
 virtual int NotifyDisconnect(ClientSocket* pClientSocket) = 0;

 //日志
 virtual void Log(const char* msg,const LOG_PRINT__TYPE type = LOG_NOTIFY) = 0;

 //处理完成端口上接受和发送udp消息的接口函数
 virtual int ProcessUDPMessage(ClientSocket* pClientSock, OVERLAPPEDEX* pOLEX);

 //收到UDP数据
 virtual int RecvUDPMessage(ClientSocket* pClinetSocket) = 0;
 
 //当accept缓冲区消耗完时,负责添加新的缓冲区
 DWORD  AcceptExThread();

 //检查连接建立后是不是很长一短时间没有发送数据,如果是则断开连接
 DWORD  TcpLinkCheckthread();

public:
 int m_iServerPort;

protected:
 HANDLE m_hAcceptExThreadEvent; //tcp接收缓冲区消耗尽触发的事件
 DWORD m_dwThreadCount;
 HANDLE hCompletePort;
 SOCKET m_listenSocket;
 SOCKET m_udpSocket;    //udp socket
 SOCKET m_udpProxySocket;    //udp 代理 socket
 INT    m_iMaxConnections;
 CClientSocketPool m_clientSocketPool;
 std::list<OVERLAPPEDEX*> m_lstOlePool; //重叠缓存池

 std::list<OVERLAPPEDEX*> m_lstOlePoolAll; //重叠缓存池

 CCriticalSection cs; //临界内存,保证多线程安全

public:
 int CloseClientSock(ClientSocket* pClientSocket);
 //2008-9-9 add
 int AddTcpSocket( ClientSocket* pClientSock );
 int AddUDPSocket(ClientSocket* pClientSock );
protected:
 //初始化IOCP,创建ICOP句柄和开启工作线程
 BOOL InitIocp(void);
 
};

 

------------------------------cpio.cpp

 

 

#include "afx.h"
#include "IOCP.h"
#include <algorithm>
#include <Objbase.h>
IOCP_API int  g_running = FALSE;

DWORD WINAPI WorkerThreadFunc(LPVOID pParam);
DWORD WINAPI AcceptExThread(LPVOID pParam);
DWORD WINAPI TcpLinkCheckthread(LPVOID pParam);


//tcp保活时间结构体
struct tcp_keepalive {
 u_long  onoff;
 u_long  keepalivetime;
 u_long  keepaliveinterval;
};

// New WSAIoctl Options
#define SIO_RCVALL            _WSAIOW(IOC_VENDOR,1)
#define SIO_RCVALL_MCAST      _WSAIOW(IOC_VENDOR,2)
#define SIO_RCVALL_IGMPMCAST  _WSAIOW(IOC_VENDOR,3)
#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
#define SIO_ABSORB_RTRALERT   _WSAIOW(IOC_VENDOR,5)
#define SIO_UCAST_IF          _WSAIOW(IOC_VENDOR,6)
#define SIO_LIMIT_BROADCASTS  _WSAIOW(IOC_VENDOR,7)
#define SIO_INDEX_BIND        _WSAIOW(IOC_VENDOR,8)
#define SIO_INDEX_MCASTIF     _WSAIOW(IOC_VENDOR,9)
#define SIO_INDEX_ADD_MCAST   _WSAIOW(IOC_VENDOR,10)
#define SIO_INDEX_DEL_MCAST   _WSAIOW(IOC_VENDOR,11)


CIOCP::CIOCP(void)
{
 hCompletePort = NULL;
 m_listenSocket = INVALID_SOCKET;
    m_udpSocket = INVALID_SOCKET;
 m_udpProxySocket = INVALID_SOCKET;
 
 m_iServerPort = 2000;
 m_iMaxConnections = 20000;
 m_dwThreadCount = 0;
 m_hAcceptExThreadEvent = ::CreateEvent(NULL, TRUE, FALSE, _T("AcceptExThreadEvent") );
}

/***********************************************************************************************************/
//Function: ~CIOCP
//Notes: 释构函数,将内存池m_lstOlePool的资源释放
//

/***********************************************************************************************************/
CIOCP::~CIOCP(void)
{
 //释放资源
 cs.Lock();  //加锁
 std::list<OVERLAPPEDEX*>::const_iterator itr = m_lstOlePoolAll.begin();
 for (; itr != m_lstOlePoolAll.end(); ++itr)
 {
  delete *itr;
 }
 m_lstOlePoolAll.clear();
 CloseHandle(m_hAcceptExThreadEvent);
 cs.Unlock();  //解锁

 if (hCompletePort != NULL)
 {
  Stop();
 }
}

BOOL CIOCP::InitIocp()
{
 m_dwThreadCount =  0;
 
 //运行标志置1
 InterlockedExchange((long *)&g_running, 1);
 
 //创建完成端口
 hCompletePort  = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
 if ( 0 == hCompletePort)
 {
  Log("创建完成端口失败!");
  return CREATE_COMPLETE_PORT_FAILURE;
 }

 SYSTEM_INFO systemInfo;
 ::GetSystemInfo(&systemInfo);
 m_dwThreadCount = systemInfo.dwNumberOfProcessors * WORKER_THREAD_PER_CPU;


 //创建Worker线程
 for (DWORD i = 0; i < m_dwThreadCount; ++i)
 {
  HANDLE h = CreateThread(NULL,0,WorkerThreadFunc,this,0,NULL);
  CloseHandle(h);
 }
 return 0;
}


// 开始服务
int CIOCP::Start(int port , int maxConnection)
{
 m_iServerPort = port;
 m_iMaxConnections = maxConnection;

 //初始化IOCP
 BOOL binit = InitIocp();
 if (binit != 0)
 {
  return binit;
 }
 //获取主机地址
 hostent*  pHostEnt = gethostbyname("");
 char*  szIpAddr = inet_ntoa(*(struct in_addr *)*pHostEnt->h_addr_list);
 int nServerip = inet_addr(szIpAddr);

 //创建Listen Socket
 m_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 if ( INVALID_SOCKET == m_listenSocket )
 {
  Log("创建监听端口失败!");
  return CREATE_LISTEN_PORT_FAILURE;
 }

 CreateIoCompletionPort((HANDLE)m_listenSocket,hCompletePort,0,m_dwThreadCount);

 //获取AcceptEx函数指针
 GUID wsaidAcceptEx = WSAID_ACCEPTEX;    
 DWORD dwBytes = 0;
 LPFN_ACCEPTEX m_lpfnAcceptEx;
 WSAIoctl(m_listenSocket,
   SIO_GET_EXTENSION_FUNCTION_POINTER,
   &wsaidAcceptEx,
   sizeof(wsaidAcceptEx),
   &m_lpfnAcceptEx,
   sizeof(m_lpfnAcceptEx),
   &dwBytes,
   NULL,
   NULL);

 //开始Listen
 SOCKADDR_IN addr;
 memset(&addr,0,sizeof(addr));
 addr.sin_family = AF_INET;  
 addr.sin_addr.s_addr =  inet_addr("0.0.0.0"); //htonl(INADDR_ANY);  
 addr.sin_port = htons(m_iServerPort);
 bind(m_listenSocket,(PSOCKADDR)&addr,sizeof(addr));  
 int res = listen(m_listenSocket, 8);


 //当tcp没有接收缓冲区的侍候,会触发此事件
 if (m_hAcceptExThreadEvent)
 {
  ::WSAEventSelect( m_listenSocket, m_hAcceptExThreadEvent, FD_ACCEPT );
  HANDLE h = CreateThread(NULL, 0, ::AcceptExThread, this, 0, NULL);
  CloseHandle(h);
 } 

 HANDLE h = CreateThread(NULL, 0, ::TcpLinkCheckthread, this, 0, NULL);
 CloseHandle(h);

 //初始化ClientSocket池
 Log("正在初始化Client Socket池,请稍候...");
 m_clientSocketPool.Initialize(m_iMaxConnections, m_listenSocket, hCompletePort);

 Log("服务器已经启动!");
 return 0;
}

 

// 停止服务
int CIOCP::Stop(void)
{
 InterlockedExchange((long *)&g_running, 0);

 //关闭Socket池中的连接
 Log("正在关闭Client Socket池,请稍候...");
 m_clientSocketPool.Close();
 
 //关闭Listen socket
 closesocket(m_listenSocket);
 m_listenSocket = INVALID_SOCKET;

 //关闭udp socket
 closesocket(m_udpSocket);
 m_udpSocket = INVALID_SOCKET;
 
 //关闭完成端口
 if (hCompletePort != NULL)
 {
  CloseHandle(hCompletePort);
  hCompletePort = NULL ;
 }

 Log("服务器停止!");
 return 0;
}

 

int CIOCP::WorkerThreadLogic(void)
{
 DWORD bytesTransferred;
 ClientSocket* pClientSock;
 OVERLAPPEDEX* pOLEX;

 while (1 == InterlockedExchange((long *)&g_running, g_running))
 {
  pClientSock = NULL;
  BOOL rtStatus = GetQueuedCompletionStatus(hCompletePort,
             &bytesTransferred,
             (LPDWORD) &pClientSock,
             (LPOVERLAPPED*)&pOLEX,
             INFINITE);

  if ( 0 == InterlockedExchange((long *)&g_running, g_running))
  {
   break;
  }

  if ( FALSE == rtStatus )
  {
    DWORD  errCode = GetLastError();
   if ( ERROR_NETNAME_DELETED  == errCode )
   {
    if (NULL == pClientSock && NULL != pOLEX)
    {
     Log("CloseClientSock");
     m_clientSocketPool.ReleaseClientSock(pOLEX->pClientSock);
    }
    else
    {
     CloseClientSock(pClientSock);
    }
   }
   else if(ERROR_OPERATION_ABORTED != errCode ||  WAIT_TIMEOUT != errCode )
   {
    Log("GetQueuedCompletionStatus 出错!");
   }
  
   continue;
  }

  //如果是udp连接
  if ( pOLEX && pOLEX->pClientSock && pOLEX->pClientSock->bIsUPDSock)
  {
   pClientSock = pOLEX->pClientSock;
   pClientSock->bytesTransferred = bytesTransferred;
   BOOL  bReadNextMessage = ProcessUDPMessage(pClientSock, pOLEX);
   if (bReadNextMessage)  //投递下一个数据接收
   {
    DWORD flag = MSG_PARTIAL;
    DWORD ioSize = 0;
    pClientSock->olex.ioType = READ;

    //设置剩余缓冲区长度
    pClientSock->olex.wsabuf.len = DATA_BUF_LENGHT  -
     ((int)pClientSock->olex.wsabuf.buf - (int)pClientSock->olex.buf);

    int rtSend = WSARecvFrom(
     pClientSock->socket,
     &pClientSock->olex.wsabuf,
     1,
     &pClientSock->bytesTransferred,
     &flag,
     (sockaddr*)pClientSock->AddressBuffer,
     &pClientSock->iAddrLen,
     (LPOVERLAPPED)&pClientSock->olex,
     0);
   }

  }
  else if( pOLEX && pOLEX->pClientSock)
  {
   pClientSock = pOLEX->pClientSock;
   pClientSock->bytesTransferred = bytesTransferred;

   int  bReadNextMessage = TRUE;
   try
   {
    bReadNextMessage = ProcessIOCPMessage(pClientSock, pOLEX);
   }
   catch (...)
   {
    Log("处理数据包异常!");
    bReadNextMessage = TRUE;
   }
   
   
   //准备接受下一个数据包
   if ( bReadNextMessage )
   {
    DWORD flag = MSG_PARTIAL;
    DWORD ioSize = 0;
    pClientSock->olex.ioType = READ;

    //设置剩余缓冲区长度
    pClientSock->olex.wsabuf.len = DATA_BUF_LENGHT  -
     ((int)pClientSock->olex.wsabuf.buf - (int)pClientSock->olex.buf);

    int rtSend = WSARecv(pClientSock->socket,
         &pClientSock->olex.wsabuf,
         1,
         &pClientSock->bytesTransferred,
         &flag,
         (LPOVERLAPPED)&pClientSock->olex,
         0);

    if ( SOCKET_ERROR == rtSend &&
     WSA_IO_PENDING != GetLastError())
    {
     //CloseClientSock(pClientSock);    
    }

   }
  }
 }

 return 0;
}


/***********************************************************************************************************/
//Function: ProcessIOCPMessage
//Notes: 处理完成端口上接受和发送数据的函数
//
//Input:  pClientSock用户端口对象,  pOLEX重叠缓冲区指针

/***********************************************************************************************************/
//处理IOCP上的消息
int CIOCP::ProcessIOCPMessage(ClientSocket* pClientSock, OVERLAPPEDEX* pOLEX)
{
 //再上次操作中是否读了数据
 BOOL  bRecved = FALSE;

 if (pOLEX && WRITE == pOLEX->ioType)
 {
  if (pOLEX->bSaveSend)  //bSaveSend表示用安全重叠方式处理数据的发送,发送完后回收资源
  {
   cs.Lock();
   m_lstOlePool.push_back(pOLEX);
   cs.Unlock();
  }
  if (!pClientSock->bIsServer)
  {
   //CloseClientSock(pClientSock);
  }
  Log("已经发送完数据!/r/n");
  bRecved = TRUE;
 }
 else
 {
  DWORD dwRet = 0;
  switch(pClientSock->olex.ioType)
  {
  case ACCEPT:
   setsockopt(pClientSock->socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
    (char *)&m_listenSocket, sizeof (pClientSock->socket));
   
   //设置保活时间为10秒,发送次数为2
   //struct tcp_keepalive alive;
   //alive.onoff = TRUE;
   //alive.keepalivetime = 100000;
   //alive.keepaliveinterval = 2;
   //if (WSAIoctl(pClientSock->socket, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
   // NULL, 0, &dwRet, NULL, NULL) == SOCKET_ERROR)
   //{
   // Log("WSAIotcl(SIO_KEEPALIVE_VALS) failed; %d/n");
   //}

   bRecved = NotifyNewConnect(pClientSock);
   break;

  case READ:
   if( 0 == pClientSock->bytesTransferred)
   {
    CloseClientSock(pClientSock);
    bRecved = TRUE;
   }
   else
    bRecved = RecvMessage(pClientSock);
   break;

  case WRITE:
   Log("已经发送完数据!");
   bRecved = TRUE;
   break;
        default:
   break;
  }
 }
    return ! bRecved;
}

/***********************************************************************************************************/
//Function: WriteMessage
//Notes: 发送数据包到完成端口,如果是udp则采用udp方式,如果是tcp socket则采用tcp方式发送
//
//Input:  ClientSocket* pClientSock 客户端口信息指针, BYTE* msg消息内容指针,int len数据长度,
//        const BOOL bSaveSend是否采用安全的重叠方式发送

/***********************************************************************************************************/
int CIOCP::WriteMessage(ClientSocket* pClientSock, BYTE* msg, int len, const BOOL bSaveSend)
{
 if (NULL == pClientSock || NULL == msg)
 {
  Log("套接字非法");
  return 0;
 }
 if (pClientSock->bIsUPDSock)  //如果是UPD socket,则采用UDP的方式发送
 {
  int addrlen = sizeof(sockaddr_in);
  int errCode = sendto(pClientSock->socket, (CHAR*)msg, len, 0,
              (sockaddr*)pClientSock->AddressBuffer, addrlen);
  if (errCode == SOCKET_ERROR)
  {
            errCode = GetLastError();
  }
  return errCode;
 }
 else if (!bSaveSend)
 {
  send(pClientSock->socket,(CHAR*)msg, len, 0);
  return 0;
 }
 else
 {
  if( len > DATA_BUF_LENGHT)
  {
   Log("发送的数据过长");
   return 0;
  }
  OVERLAPPEDEX* pOlex = NULL;

  //上锁
  cs.Lock();
  if (m_lstOlePool.empty())  //没有可用资源则new
  {
   pOlex = new OVERLAPPEDEX;
   m_lstOlePoolAll.push_back(pOlex);
   if (m_lstOlePoolAll.size() > 10000)//防止快速过量申请缓存
   {
    Sleep(m_lstOlePoolAll.size()/10000);
   }
  }
  else  //从缓冲池中分配
  {
   pOlex = *m_lstOlePool.begin();
   m_lstOlePool.pop_front();
  }
  cs.Unlock(); //解锁
  
  *pOlex = pClientSock->olex;

  pOlex->bSaveSend = TRUE;
  memcpy(&(pOlex->buf), msg, len);

  pOlex->ioType = WRITE;
  pOlex->wsabuf.len = len;
  pOlex->wsabuf.buf = (CHAR*)&(pOlex->buf);
  pOlex->bytesTransferred = len;


  //发送数据到客户端
  DWORD flag = MSG_PARTIAL;
  int rtSend = WSASend(pClientSock->socket,
   &pOlex->wsabuf,
   1,
   &(pOlex->bytesTransferred),
   flag,
   (LPOVERLAPPED)pOlex,
   0);

  if ( SOCKET_ERROR == rtSend &&
   WSA_IO_PENDING != GetLastError())
  {
   delete pOlex;
   CloseClientSock(pClientSock);    
  }
 }
 return 0;

}

/***********************************************************************************************************/
//Function: WriteMessage
//Notes: 向一个UDP地址发送数据
//
//Input:  ClientSocket* pClientSock 客户端口信息指针, BYTE* msg消息内容指针,int len数据长度,
//        const BOOL bSaveSend是否采用安全的重叠方式发送

/***********************************************************************************************************/
int CIOCP::WriteMessageTo(ClientSocket* pClinetSocket, BYTE* msg, int len, sockaddr_in& addrTo,
       const BOOL bSaveSend)
{
 //如果不是udp数据的套接字,则报错
 if (!pClinetSocket->bIsUPDSock)
 {
  Log("WriteMessageTo 只能发送udp数据包!");
  return 0;
 }
 if (bSaveSend)  //使用阻塞的方式发送
 {
  int addrlen = sizeof(sockaddr_in);
  int errCode = sendto(m_udpProxySocket, (CHAR*)msg, len, 0,
   (sockaddr*)&addrTo, addrlen);
  if (errCode == SOCKET_ERROR)
  {
   errCode = GetLastError();
  }
 }
 {
  if( len > DATA_BUF_LENGHT)
  {
   Log("发送的数据过长");
   return 0;
  }
  OVERLAPPEDEX* pOlex = NULL;

  //上锁
  cs.Lock();
  if (m_lstOlePool.empty())  //没有可用资源则new
  {
   pOlex = new OVERLAPPEDEX;
   m_lstOlePoolAll.push_back(pOlex);
   if (m_lstOlePoolAll.size() >= 100)
   {
    m_lstOlePool.insert(m_lstOlePool.end() ,m_lstOlePoolAll.begin() ,m_lstOlePoolAll.end());
   }
  }
  else  //从缓冲池中分配
  {
   pOlex = *m_lstOlePool.begin();
   m_lstOlePool.pop_front();
  }
  cs.Unlock(); //解锁

  *pOlex = pClinetSocket->olex;

  pOlex->bSaveSend = TRUE;
  memcpy(&(pOlex->buf), msg, len);

  pOlex->ioType = WRITE;
  pOlex->wsabuf.len = len;
  pOlex->wsabuf.buf = (CHAR*)&(pOlex->buf);
  pOlex->bytesTransferred = len;

  int addrlen = sizeof(sockaddr_in);

  //发送数据到客户端
  DWORD flag = 0;//MSG_WAITALL;
  int rtSend = WSASendTo(pClinetSocket->socket,
   &pOlex->wsabuf,
   1,
   &(pOlex->bytesTransferred ),
   flag,
   (sockaddr*)&addrTo,
   addrlen,
   (LPOVERLAPPED)pOlex,
   0);
 }
 return 0;
}

//线程函数入口
DWORD WINAPI WorkerThreadFunc(LPVOID pParam)
{
// ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
 ((CIOCP*)pParam)->WorkerThreadLogic(); 

 return 0;
}


int CIOCP::CloseClientSock( ClientSocket* pClientSocket )
{
 if (pClientSocket && !pClientSocket->bIsUPDSock)  //如果是tcp连接
 {
  m_clientSocketPool.ReleaseClientSock(pClientSocket);
  NotifyDisconnect(pClientSocket);
 }
 return 0;
}


/***********************************************************************************************************/
//Function: ProcessUDPMessage
//Notes: 处理完成端口上UDP接受和发送数据的函数
//
//Input:  pClientSock用户端口对象,  pOLEX重叠缓冲区指针

/***********************************************************************************************************/
//处理IOCP上的消息
int CIOCP::ProcessUDPMessage(ClientSocket* pClientSock, OVERLAPPEDEX* pOLEX)
{
 //再上次操作中是否读完了数据
 BOOL  bRecved = FALSE;
 if (pOLEX && WRITE == pOLEX->ioType)
 {
  if (pOLEX->bSaveSend)  //bSaveSend表示用安全重叠方式处理数据的发送,发送完后回收资源
  {
   cs.Lock();
   m_lstOlePool.push_back(pOLEX);
   cs.Unlock();
  }
  Log("已经发送完数据!");
  bRecved = TRUE;
 }
 else
 {
  switch(pClientSock->olex.ioType)
  {
  case READ:
   bRecved = RecvUDPMessage(pClientSock);
   break;

  case WRITE:
   Log("已经发送完UDP数据!");
   bRecved = TRUE;
   break;
  default:
   break;
  }
 }

 return !bRecved;
}

 

//增加一个TCP连接,并投递一个读操作
int CIOCP::AddTcpSocket( ClientSocket* pClientSock )
{
 if ( pClientSock )
 {
  // if (pClientSock->bIsServer)
  // {
  // clientSocketPool.SettingClientSocket(pClientSock);
  //}
  // else
  //{
  //关联完成端口
  CreateIoCompletionPort((HANDLE)pClientSock->socket, hCompletePort, (DWORD)pClientSock, 0);
  
  //异步等待Socket连接
  memset( &(pClientSock->olex) , 0, sizeof(OVERLAPPEDEX));
  
  pClientSock->bIsUPDSock = FALSE;   //设置UDP连接标志
  pClientSock->olex.pClientSock = pClientSock;
  
  pClientSock->bytesTransferred = 0;
  
  DWORD flag = MSG_PARTIAL;
  DWORD ioSize = 0;
  pClientSock->olex.ioType = READ;
  
  //设置剩余缓冲区长度
  pClientSock->olex.wsabuf.buf = pClientSock->olex.buf;
  pClientSock->olex.wsabuf.len = DATA_BUF_LENGHT;
  
  int rtSend = WSARecv(pClientSock->socket,
   &pClientSock->olex.wsabuf,
   1,
   &pClientSock->bytesTransferred,
   &flag,
   (LPOVERLAPPED)&pClientSock->olex,
   0);
  
  if ( SOCKET_ERROR == rtSend &&
   WSA_IO_PENDING != GetLastError())
  {
   return FALSE;
   //CloseClientSock(pClientSock);    
  }
  //}
  
 }
 else
 {
  return FALSE;
 }
 return TRUE;
}


int CIOCP::AddUDPSocket( ClientSocket*  pClientSock)
{
 int res = 0;
 if ( pClientSock )
 {
  SOCKET socket = pClientSock->socket;

  //关联完成端口
  CreateIoCompletionPort((HANDLE)pClientSock->socket, hCompletePort,(DWORD)pClientSock, 0);

  //准备接受数据包

  //异步等待Socket连接
  memset( &(pClientSock->olex) , 0, sizeof(OVERLAPPEDEX));
  pClientSock->olex.pClientSock = pClientSock;
  pClientSock->olex.wsabuf.buf = pClientSock->olex.buf;
  pClientSock->bytesTransferred = 0;
  pClientSock->bIsUPDSock = TRUE;   //设置UDP连接标志
  pClientSock->iAddrLen = sizeof(sockaddr_in);

  DWORD flag = MSG_PARTIAL;
  DWORD ioSize = 0;
  pClientSock->olex.ioType = READ;
  pClientSock->olex.wsabuf.len = DATA_BUF_LENGHT;

  int rtSend = WSARecvFrom(
   pClientSock->socket,
   &pClientSock->olex.wsabuf,
   1,
   &pClientSock->bytesTransferred,
   &flag,
   (sockaddr*)pClientSock->AddressBuffer,
   &pClientSock->iAddrLen,
   (LPOVERLAPPED)&pClientSock->olex,
   0);
  res = GetLastError();
  if ( SOCKET_ERROR == rtSend &&
   WSA_IO_PENDING != GetLastError())
  {
   closesocket(pClientSock->socket);
   return FALSE;
  }
  pClientSock = NULL;
 }
 return TRUE;
}

/***********************************************************************************************************/
//Function: AcceptExThread
//Notes: 处理完成端口上UDP接受和发送数据的函数

/***********************************************************************************************************/
DWORD  CIOCP::AcceptExThread()
{
 // 负责保证有足够多的 AcceptEx 可以接受连接请求的线程
 while (1 == InterlockedExchange((long *)&g_running, g_running))
 {
  DWORD dwRes = ::WaitForSingleObject( m_hAcceptExThreadEvent, INFINITE );
  if( dwRes == WAIT_FAILED )
  {
   break;
  }
  ::ResetEvent( m_hAcceptExThreadEvent );

  //当资源不够时,每次增加10个
  m_clientSocketPool.AddTCPAcceptBuff(10);
 }
 return 0;
}

/***********************************************************************************************************/
//Function: AcceptExThread
//Notes: /线程函数入口
//
/***********************************************************************************************************/
DWORD WINAPI AcceptExThread(LPVOID pParam)
{
 if (pParam)
 {
  ((CIOCP*)pParam)->AcceptExThread(); 
 }
 return 0;
}

/***********************************************************************************************************/
//Function: TcpLinkCheckthread
//Notes: /线程函数入口
//
/***********************************************************************************************************/
DWORD WINAPI TcpLinkCheckthread(LPVOID pParam)
{
 if (pParam)
 {
  ((CIOCP*)pParam)->AcceptExThread(); 
 }
 return 0;
}

/***********************************************************************************************************/
//Function: TcpLinkCheckthread
//Notes: 检查tcp连接是不是建立后没有发送数据,如果建立连接后5分钟不发送数据则自动断开

/***********************************************************************************************************/
DWORD  CIOCP::TcpLinkCheckthread()
{
 //下面方法还不能防止攻击,暂时屏蔽
 return 0;

 // 负责保证有足够多的 AcceptEx 可以接受连接请求的线程
 std::list<ClientSocket*> clientSocketList;
 int iSecs = 0;
 int iBytes =  sizeof( int );
 while (1 == InterlockedExchange((long *)&g_running, g_running))
 {
  //获取所有的连接缓冲区
  m_clientSocketPool.GetTcpClientSock(clientSocketList);
  
  std::list<ClientSocket*>::iterator itr = clientSocketList.begin();
  for (; itr != clientSocketList.end(); ++itr)
  {
   if (*itr)
   {
    iSecs = 0;
    getsockopt((*itr)->socket, SOL_SOCKET, SO_CONNECT_TIME, (char *)&iSecs, &iBytes ); 
    
    //避免一个连接占用时间过长
    if (iSecs > 6000000)
    {
     CloseClientSock(*itr);
    }
   }
  }
  //没5分钟检查一次
  Sleep(300000);
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值