winsock 完成端口 服务器模型(2)

//IOCPServer.cpp

#include "StdAfx.h"
#include "IOCPServer.h"

IOCPServer::IOCPServer(void)
{
 this->InitSocket();
 this->m_bIsServerStart=true;

 this->m_pFreeBufferList=NULL;
 InitializeCriticalSection(&m_FreeBufferListLock);
 this->m_FreeBufferCount=0;

 this->m_pFreeContextList=NULL;
 this->m_FreeContextCount=0;
 InitializeCriticalSection(&this->m_FreeContextListLock);

 this->m_pConnectContextList=NULL;
 this->m_ConnectContextCount=0;
 InitializeCriticalSection(&this->m_ConnectContextListLock);

 this->m_hAcceptEvent=WSACreateEvent();
 this->m_hRePostAcceptEvent=::CreateEvent(NULL,false,false,NULL);

 this->m_pPostAcceptList=NULL;
 ::InitializeCriticalSection(&this->m_PostAcceptListLock);

 this->m_bShutDown=false;
}
void IOCPServer::ResetValue()
{
 this->m_bIsServerStart=true;

 this->m_pFreeBufferList=NULL;
 this->m_FreeBufferCount=0;

 this->m_pFreeContextList=NULL;
 this->m_FreeContextCount=0;

 this->m_pConnectContextList=NULL;
 this->m_ConnectContextCount=0;

 this->m_hAcceptEvent=WSACreateEvent();

 this->m_pPostAcceptList=NULL;

 this->m_bShutDown=false;
}
bool IOCPServer::GetIsServerStart()
{
 return this->m_bIsServerStart;
}

char * IOCPServer::GetErrorMsg()
{
 return this->m_pErrorMsg;
}

IOCPServer::~IOCPServer(void)
{
 CloseHandle(this->m_hAcceptEvent);
 CloseHandle(this->m_hRePostAcceptEvent);
 ::DeleteCriticalSection(&this->m_FreeBufferListLock);
 ::DeleteCriticalSection(&this->m_FreeContextListLock);
 ::DeleteCriticalSection(&this->m_ConnectContextListLock);
 ::DeleteCriticalSection(&this->m_PostAcceptListLock);
 ::WSACleanup();
}

void IOCPServer::InitSocket()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 
 wVersionRequested = MAKEWORD( 2, 2 );
 
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  return;
 }                                   
 if ( LOBYTE( wsaData.wVersion ) != 2 ||
   HIBYTE( wsaData.wVersion ) != 2 ) {
  WSACleanup( );
  return;
 }
}
void IOCPServer::InsertToPostAccept(IOCPBUFFER *pBuffer)
{
 if(pBuffer!=NULL)
 {
  ::EnterCriticalSection(&this->m_PostAcceptListLock);
  pBuffer->pNext=this->m_pPostAcceptList;
  this->m_pPostAcceptList=pBuffer;
  ::LeaveCriticalSection(&this->m_PostAcceptListLock);
 }
}
void IOCPServer::RemoveFormPostAccept(IOCPBUFFER *pBuffer)
{
 if(pBuffer!=NULL)
 {
  ::EnterCriticalSection(&this->m_PostAcceptListLock);
  IOCPBUFFER *pTemp=this->m_pPostAcceptList;
  if(pTemp==pBuffer)
  {
   this->m_pPostAcceptList=this->m_pPostAcceptList->pNext;
  }
  else
  {
   while(pTemp!=NULL&&pTemp->pNext!=pBuffer)
   {
    pTemp=pTemp->pNext;
   }
   if(pTemp!=NULL)
   {
    pTemp->pNext=pBuffer->pNext;
   }
  }
  ::LeaveCriticalSection(&this->m_PostAcceptListLock);
 }
}
IOCPBUFFER* IOCPServer::AllocBuffer(int nLen)
{
 IOCPBUFFER* pBuffer=NULL;
 ::EnterCriticalSection(&this->m_FreeBufferListLock);
 if(this->m_pFreeBufferList==NULL) //如果内存池为空
 {
  //让pBuffer->buf就在pBuffer之向
  pBuffer=(IOCPBUFFER*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IOCPBUFFER)+BUFFER_SIZE);
 }
 else
 {
  pBuffer=this->m_pFreeBufferList;
  pBuffer->pNext=NULL;
  m_pFreeBufferList=m_pFreeBufferList->pNext;
  this->m_FreeBufferCount--;
 }
 ::LeaveCriticalSection(&this->m_FreeBufferListLock);
 if(pBuffer!=NULL)
 {
  pBuffer->buf=(char *)(pBuffer+1);
  pBuffer->nLen;
 }
 return pBuffer;
}

void IOCPServer::FreeBuffer(IOCPBUFFER* pBuffer)
{
 ::EnterCriticalSection(&this->m_FreeBufferListLock);
 if(this->m_FreeBufferCount<=MAXFREEBUFFERS)
 {
  //将内存块放回内存池中
  ::ZeroMemory(pBuffer,sizeof(IOCPBUFFER)+BUFFER_SIZE);
  pBuffer->pNext=this->m_pFreeBufferList;
  this->m_pFreeBufferList=pBuffer;
  this->m_FreeBufferCount++;
 }
 else
 {
  //已达到内存池的最大数,释放缓冲区对象所在的空间
  HeapFree(GetProcessHeap,0,pBuffer);
 }
 ::LeaveCriticalSection(&this->m_FreeBufferListLock);
}

IOCPCONTEXT* IOCPServer::AllocContext(SOCKET s)
{
 IOCPCONTEXT* pContext=NULL;
 ::EnterCriticalSection(&this->m_FreeContextListLock);
 if(this->m_pFreeContextList==NULL)
 {
  //如果列表为空则重新分配一个上下文对象
  pContext=(IOCPCONTEXT*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IOCPCONTEXT));
  if(pContext!=NULL)
  {
   ::InitializeCriticalSection(&pContext->lock);
  }
 }
 else
 {
  pContext=this->m_pFreeContextList;
  this->m_pFreeContextList=this->m_pFreeContextList->pNext;
  pContext->pNext=NULL;
  this->m_FreeContextCount--;
 }
 ::LeaveCriticalSection(&this->m_FreeContextListLock);
 if(pContext!=NULL)
 {
  pContext->s=s;
 }
 return pContext;
}

void IOCPServer::FreeContext(IOCPCONTEXT* pContext)
{
 if(pContext->s!=INVALID_SOCKET)
 {
  closesocket(pContext->s);
 }
 IOCPBUFFER* pBuffer;
 ::EnterCriticalSection(&pContext->lock);
 while(pContext->pOutofOrederReads!=NULL)
 {
  pBuffer=pContext->pOutofOrederReads->pNext;
  this->FreeBuffer(pContext->pOutofOrederReads);
  pContext->pOutofOrederReads=pBuffer;
 }
 ::LeaveCriticalSection(&pContext->lock);
 ::EnterCriticalSection(&this->m_FreeContextListLock);
 if(this->m_FreeContextCount<MAXFREECONTEXTS)
 {
  CRITICAL_SECTION csTemp=pContext->lock;
  ::ZeroMemory(pContext,sizeof(IOCPCONTEXT));
  pContext->lock=csTemp;
  pContext->pNext=this->m_pFreeContextList;
  this->m_pFreeContextList=pContext;
  this->m_FreeContextCount++;
 }
 else
 {
  ::DeleteCriticalSection(&pContext->lock);
  ::HeapFree(GetProcessHeap(),0,pContext);
 }
 ::LeaveCriticalSection(&this->m_FreeContextListLock);
}

bool IOCPServer::AddConnection(IOCPCONTEXT* pContext)
{
 ::EnterCriticalSection(&this->m_ConnectContextListLock);
 if(this->m_ConnectContextCount>MAXCONNECTIONS)
 {
  ::LeaveCriticalSection(&this->m_ConnectContextListLock);
  return false;
 }
 pContext->pNext=this->m_pConnectContextList;
 this->m_pConnectContextList=pContext;
 this->m_ConnectContextCount++;
 ::LeaveCriticalSection(&this->m_ConnectContextListLock);
 return true;
}

void IOCPServer::CloseConnection(IOCPCONTEXT* pContext)
{
 ::EnterCriticalSection(&this->m_ConnectContextListLock);
 IOCPCONTEXT* pTemp=this->m_pConnectContextList;
 if(pTemp==pContext)
 {
  this->m_pConnectContextList=pContext->pNext;
  pContext->pNext=NULL;
  this->m_ConnectContextCount--;
 }
 else
 {
  while(pTemp!=NULL&&pTemp->pNext!=pContext)
  {
   pTemp=pTemp->pNext;
  }
  if(pTemp!=NULL)
  {
   pTemp->pNext=pContext->pNext;
   this->m_ConnectContextCount--;
  }
 }
 ::LeaveCriticalSection(&this->m_ConnectContextListLock);

 ::EnterCriticalSection(&pContext->lock);
 if(pContext->s!=INVALID_SOCKET)
 {
  closesocket(pContext->s);
  pContext->s=INVALID_SOCKET;
 }
 ::LeaveCriticalSection(&pContext->lock);
}

void IOCPServer::CloseAllConnects()
{
 ::EnterCriticalSection(&this->m_ConnectContextListLock);
 IOCPCONTEXT* pTemp=this->m_pConnectContextList;
 while(pTemp!=NULL)
 {
  this->m_pConnectContextList=pTemp->pNext;
  ::EnterCriticalSection(&pTemp->lock);
  if(pTemp->s!=INVALID_SOCKET)
  {
   closesocket(pTemp->s);
   pTemp->s=INVALID_SOCKET;
  }
  ::LeaveCriticalSection(&pTemp->lock);
  pTemp=this->m_pConnectContextList;
 }
 ::LeaveCriticalSection(&this->m_ConnectContextListLock);
}

void IOCPServer::FreeBuffers()
{
 ::EnterCriticalSection(&this->m_FreeBufferListLock);
 IOCPBUFFER *pBuffer=this->m_pFreeBufferList;
 while(pBuffer!=NULL)
 {
  this->m_pFreeBufferList=pBuffer->pNext;
  ::HeapFree(::GetProcessHeap(),0,pBuffer);
  pBuffer=this->m_pFreeBufferList;
 }
 ::LeaveCriticalSection(&this->m_FreeBufferListLock);
}
void IOCPServer::FreeContexts()
{
 ::EnterCriticalSection(&this->m_FreeContextListLock);
 IOCPCONTEXT *pContext=this->m_pFreeContextList;
 while(pContext!=NULL)
 {
  this->m_pFreeContextList=pContext->pNext;
  ::HeapFree(::GetProcessHeap(),0,pContext);
  pContext=this->m_pFreeContextList;
 }
 ::LeaveCriticalSection(&this->m_FreeContextListLock);
}

bool IOCPServer::PostAccept(IOCPBUFFER* pBuffer)
{
 pBuffer->nOperationType=OP_ACCEPT;
 pBuffer->sClient=::WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
 DWORD dwBytes;
 BOOL bOK=this->m_lpfnAcceptEx(this->m_sListen,pBuffer->sClient,pBuffer->buf,BUFFER_SIZE-(sizeof(sockaddr_in)+16)*2,sizeof(sockaddr_in)+16,
  sizeof(sockaddr_in)+16,&dwBytes,&pBuffer->ol);
 if(!bOK)
 {
  if(WSA_IO_PENDING!=WSAGetLastError())
  {
   return false;
  }
 }
 return true;
}

bool IOCPServer::PostRecv(IOCPBUFFER* pBuffer,IOCPCONTEXT* pContext)
{
 pBuffer->nOperationType=OP_RECV;

 ::EnterCriticalSection(&pContext->lock);

 pBuffer->nSequenceNumber=pContext->nReadSequence;
 ::WSABUF buf;
 buf.buf=pBuffer->buf;
 buf.len=BUFFER_SIZE;
 DWORD dwBytes;
 DWORD dwFlags=0;
 if(::WSARecv(pContext->s,&buf,1,&dwBytes,&dwFlags,&pBuffer->ol,NULL))
 {
  if(WSA_IO_PENDING!=WSAGetLastError())
  {
   ::LeaveCriticalSection(&pContext->lock);
   return false;
  }
 }
 pContext->nOutstandingRecv++;
 pContext->nReadSequence++;
 ::LeaveCriticalSection(&pContext->lock);
 return true;
}

bool IOCPServer::PostSend(IOCPBUFFER* pBuffer, IOCPCONTEXT* pContext)
{
 pBuffer->nOperationType=OP_SEND;
 ::EnterCriticalSection(&pContext->lock);
 DWORD dwBytes;
 DWORD dwFlags=0;
 WSABUF buf;
 buf.buf=pBuffer->buf;
 buf.len=pBuffer->nLen;
 if(::WSASend(pContext->s,&buf,1,&dwBytes,dwFlags,&pBuffer->ol,NULL))
 {
  if(WSA_IO_PENDING!=WSAGetLastError())
  {
   ::LeaveCriticalSection(&pContext->lock);
   return false;
  }
 }
 pContext->nOutstandingSend++;
 ::LeaveCriticalSection(&pContext->lock);
 return true;
}

IOCPBUFFER* IOCPServer::GetNextReadBuffer(IOCPCONTEXT* pContext, IOCPBUFFER* pBuffer)
{
 ::EnterCriticalSection(&pContext->lock);
 IOCPBUFFER* ptr;
 if(pBuffer!=NULL)
 {
  if(pBuffer->nSequenceNumber==pContext->nCurrentSequence)
  {
   ::LeaveCriticalSection(&pContext->lock);
   return pBuffer;
  }

  pBuffer->pNext=NULL;
  ptr=pContext->pOutofOrederReads;
  IOCPBUFFER* pre=NULL;
  while(ptr!=NULL)
  {
   if(pBuffer->nSequenceNumber<ptr->nSequenceNumber)
   {
    break;
   }
   pre=ptr;
   ptr=ptr->pNext;
  }
  if(pre==NULL)
  {
   pBuffer->pNext=pContext->pOutofOrederReads;
   pContext->pOutofOrederReads=pBuffer;
  }
  else
  {
   pBuffer->pNext=pre->pNext;
   pre->pNext=pBuffer;
  }
 }
 ptr=pContext->pOutofOrederReads;
 if((ptr!=NULL)&&(ptr->nSequenceNumber==pContext->nCurrentSequence))
 {
  pContext->pOutofOrederReads=pContext->pOutofOrederReads->pNext;
  ::LeaveCriticalSection(&pContext->lock);
  return ptr;
 }
 ::LeaveCriticalSection(&pContext->lock);
 return NULL;
}

void IOCPServer::Start()
{
 this->m_sListen=::WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
 sockaddr_in localAddr;
 localAddr.sin_addr.S_un.S_addr=INADDR_ANY;
 localAddr.sin_family=AF_INET;
 localAddr.sin_port=htons(4567);

 if(SOCKET_ERROR == bind(this->m_sListen,(sockaddr *)&localAddr,sizeof(localAddr)))
 {
  this->m_bIsServerStart=false;
  this->m_pErrorMsg="Failed To Bind Listen Socket";
  return;
 }
 
 listen(this->m_sListen,200);

 m_hCompletion=::CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
 
 if(this->m_hCompletion==NULL)
 {
  this->m_bIsServerStart=false;
  this->m_pErrorMsg="Failed To Create IO Completion Port";
  return;
 }
 //加载AcceptEx函数
 GUID GuidAcceptEx = WSAID_ACCEPTEX;
 DWORD dwBytes;
 ::WSAIoctl(m_sListen,
  SIO_GET_EXTENSION_FUNCTION_POINTER,
  &GuidAcceptEx,
  sizeof(GuidAcceptEx),
  &m_lpfnAcceptEx,
  sizeof(m_lpfnAcceptEx),
  &dwBytes,
  NULL,
  NULL);
 GUID GuidGetAddr=WSAID_GETACCEPTEXSOCKADDRS;
 ::WSAIoctl(m_sListen,SIO_GET_EXTENSION_FUNCTION_POINTER,&GuidGetAddr,sizeof(GuidGetAddr),&this->m_lpfnGetAddr,sizeof(this->m_lpfnGetAddr),&dwBytes,NULL,
  NULL);
 ::CreateIoCompletionPort((HANDLE)this->m_sListen,this->m_hCompletion,0,0);
 
 ::WSAEventSelect(this->m_sListen,this->m_hAcceptEvent,FD_ACCEPT);
 m_hListenThread=::CreateThread(NULL,0,_ListenThreadProc,this,0,NULL); //创建监听线程
}

DWORD WINAPI IOCPServer::_ListenThreadProc(LPVOID lpParam)
{
 IOCPServer *pThis=(IOCPServer *)lpParam;

 // 先在监听套节字上投递几个Accept I/O
 IOCPBUFFER* pBuffer=NULL;
 for(int i=0;i<10;i++)
 {
  pBuffer=pThis->AllocBuffer(BUFFER_SIZE);
  if(pBuffer!=NULL)
  {
   if(pThis->PostAccept(pBuffer))
   {
    pThis->InsertToPostAccept(pBuffer);
   }
  }
  else
  {
   return -1;
  }
 }
 
 //创建两个工作线程
 for(int i=0;i<2;i++)
 {
  pThis->m_hWorkThread[i]=CreateThread(NULL,0,_WorkerThreadProc,pThis,0,NULL);
 }

 HANDLE events[10];
 events[0]=pThis->m_hAcceptEvent;
 events[1]=pThis->m_hRePostAcceptEvent;

 while(true)
 {
  int nIndex=::WaitForMultipleObjects(2,events,false,60*1000);
  if(pThis->m_bShutDown==true || nIndex==WSA_WAIT_FAILED)
  {
   pThis->CloseAllConnects();
   ::Sleep(1000);
   closesocket(pThis->m_sListen);
   ::Sleep(1000);
   for(int i=0;i<2;i++)
   {
    ::PostQueuedCompletionStatus(pThis->m_hCompletion,-1,0,0);
   }

   ::WaitForMultipleObjects(2,pThis->m_hWorkThread,true,INFINITE);

   for(int i=0;i<2;i++)
   {
    CloseHandle(pThis->m_hWorkThread[i]);
   }
   pThis->FreeBuffers();
   pThis->FreeContexts();
   ResetEvent(pThis->m_hAcceptEvent);
   ResetEvent(pThis->m_hRePostAcceptEvent);
   pThis->ResetValue();
   ExitThread(0);
  }
  if(WSA_WAIT_TIMEOUT==nIndex)
  {
   IOCPBUFFER *pBuffer=pThis->m_pPostAcceptList;
   while(pBuffer!=NULL)
   {
    int nSeconds;
    int nLen=sizeof(int);
    ::getsockopt(pBuffer->sClient,SOL_SOCKET,SO_CONNECT_TIME,(char *)&nSeconds, &nLen);
    if(nSeconds!=-1&&nSeconds>2*60)
    {
     closesocket(pBuffer->sClient);
     pBuffer->sClient=INVALID_SOCKET;
    }
    pBuffer=pBuffer->pNext;
   }
  }
  else
  {
   nIndex=nIndex-WSA_WAIT_EVENT_0;
   switch(nIndex)
   {
   case 0:
    WSANETWORKEVENTS ne;
    ::WSAEnumNetworkEvents(pThis->m_sListen,events[0],&ne);
    if(ne.lNetworkEvents&FD_ACCEPT)
    {
     //accept不够用了,投出更多的accept
     for(int i=0;i<50;i++)
     {
      IOCPBUFFER *pBuffer=pThis->AllocBuffer(BUFFER_SIZE);
      if(pThis->PostAccept(pBuffer))
      {
       pThis->InsertToPostAccept(pBuffer);
      }
     }
    }
    break;
   case 1:
    //重投一个accept
    IOCPBUFFER *pBuffer=pThis->AllocBuffer(BUFFER_SIZE);
    if(pThis->PostAccept(pBuffer))
    {
     pThis->InsertToPostAccept(pBuffer);
    }
    break;
   }
  }
 }
 return 0;
}

DWORD WINAPI IOCPServer::_WorkerThreadProc(LPVOID lpParam)
{
 IOCPServer *pThis=(IOCPServer *)lpParam;
 DWORD dwTrans;
 IOCPCONTEXT* pContext;
 IOCPBUFFER* pBuffer;

 while(true)
 {
  BOOL bOK=::GetQueuedCompletionStatus(pThis->m_hCompletion,&dwTrans,(DWORD *)&pContext,(LPOVERLAPPED *)&pBuffer,WSA_INFINITE);
  if(pContext!=NULL)
  {
   EnterCriticalSection(&pContext->lock);
   if(pBuffer->nOperationType==OP_RECV)
   {
    pContext->nOutstandingRecv--;
   }
   if(pBuffer->nOperationType==OP_SEND)
   {
    pContext->nOutstandingSend--;
   }
   LeaveCriticalSection(&pContext->lock);
  }
  else
  {
   pThis->RemoveFormPostAccept(pBuffer);
  }
  if(dwTrans==-1)
  {
   //用户通知退出
#ifdef _DEBUG
   ::OutputDebugString(L"WorkerThread Exit /n");
#endif
   ExitThread(0);
  }
  if(!bOK)
  {
   //在此套接字上有错
   if(pBuffer->nOperationType==OP_ACCEPT)
   {
    //如果是接收客户连接出错,也就是client socket出错
    if(pBuffer->sClient!=INVALID_SOCKET)
    {
     closesocket(pBuffer->sClient);
     pBuffer->sClient=INVALID_SOCKET;
    }
    ::SetEvent(pThis->m_hRePostAcceptEvent);
   }
   else
   {
    //必需关闭socket ,以便其它的I/O可以立即返回
    if(pContext->s!=INVALID_SOCKET)
    {
     closesocket(pContext->s);
     pContext->s=INVALID_SOCKET;
    }
    if(pContext->nOutstandingRecv==0&&pContext->pOutofOrederReads==0)
    {
     pThis->FreeContext(pContext);
    }
   }
   pThis->FreeBuffer(pBuffer);
  }
  else
  {
   switch(pBuffer->nOperationType)
   {
   case OP_ACCEPT:
    if(dwTrans==0)
    {
#ifdef _DEBUG
     ::OutputDebugString(L"a none send client socket closed /n");
#endif
     if(pBuffer->sClient!=INVALID_SOCKET)
     {
      closesocket(pBuffer->sClient);
      pBuffer->sClient=INVALID_SOCKET;
     }
    }
    else
    {
     //有新连接到
     IOCPCONTEXT *pNewContext=pThis->AllocContext(pBuffer->sClient);
     if(pNewContext!=NULL)
     {
      if(pThis->AddConnection(pNewContext))
      {
       //获取新连接的地址信息
       int nLocalLen,nRemoteLen;
       PSOCKADDR pLocalAddr,pRemoteAddr;
       pThis->m_lpfnGetAddr(pBuffer->buf,pBuffer->nLen-(sizeof(sockaddr_in)+16)*2,sizeof(sockaddr_in)+16,sizeof(sockaddr_in)+16,
        (sockaddr **)&pLocalAddr,&nLocalLen,(sockaddr**)&pRemoteAddr,&nRemoteLen);
       memcpy(&pNewContext->addrLocal,pLocalAddr,nLocalLen);
       memcpy(&pNewContext->addrRemote,pRemoteAddr,nRemoteLen);
 #ifdef _DEBUG
       OutputDebugString(L"a new client connect/n");
 #endif
       pBuffer->nLen=dwTrans;
       pThis->ConnectionComplete(pNewContext);  //通知已建立连接
       pThis->CompletedRecvDate(pBuffer,pNewContext);  //通知新数据到达
       
       ::CreateIoCompletionPort((HANDLE)pNewContext->s,pThis->m_hCompletion,(DWORD)pNewContext,0);
       for(int i=0;i<5;i++)
       {
        //为新连接上的客户投递Recv
        IOCPBUFFER* p=pThis->AllocBuffer(BUFFER_SIZE);
        if(p!=NULL)
        {
         if(!pThis->PostRecv(p,pNewContext))
         {
          pThis->CloseConnection(pNewContext);
          break;
         }
        }
        else
        {
         pThis->CloseConnection(pNewContext);
         break;
        }
       }

      }
      else
      {
       pThis->CloseConnection(pNewContext);
#ifdef _DEBUG
       OutputDebugString(L"max connections/n");
#endif
       pThis->FreeContext(pNewContext);
      }
     }
     else
     {
#ifdef _DEBUG
      ::OutputDebugString(L"Fail To Alloc Context/n");
#endif
      closesocket(pBuffer->sClient);
      pBuffer->sClient=INVALID_SOCKET;
     }
    }
    pThis->FreeBuffer(pBuffer);
    ::SetEvent(pThis->m_hRePostAcceptEvent);
    break;
   case OP_RECV:
    if(dwTrans==0)
    {
     pThis->CloseConnection(pContext);
     if(pContext->nOutstandingRecv==0)
     {
      pThis->DisConnection(pContext);//通知断开连接
      pThis->FreeContext(pContext);
#ifdef _DEBUG
      OutputDebugString(L"a client socket closed/n");
#endif
     }
     pThis->FreeBuffer(pBuffer);
    }
    else
    {
     pBuffer->nLen=dwTrans;
     IOCPBUFFER* pTempBuffer=pThis->GetNextReadBuffer(pContext,pBuffer);
     while(pTempBuffer!=NULL)
     {
      pThis->CompletedRecvDate(pTempBuffer,pContext);
      EnterCriticalSection(&pContext->lock);
      pContext->nCurrentSequence++;
      LeaveCriticalSection(&pContext->lock);
      pThis->FreeBuffer(pTempBuffer);
      pTempBuffer=pThis->GetNextReadBuffer(pContext,pTempBuffer);
     }
     pTempBuffer=pThis->AllocBuffer(BUFFER_SIZE);
     if(pTempBuffer==NULL||!pThis->PostRecv(pTempBuffer,pContext))
     {
      pThis->CloseConnection(pContext);
      if(pTempBuffer!=NULL)
      {
       pThis->FreeBuffer(pTempBuffer);
      }
     }
    }
    break;
   case OP_SEND:
    if(dwTrans==0)
    {
     pBuffer->nLen=0;
     pThis->CloseConnection(pContext);
     if(pContext->nOutstandingRecv==0&&pContext->nOutstandingSend==0)
     {
      pThis->DisConnection(pContext);//通知断开连接
      pThis->FreeContext(pContext);
     }
     pThis->FreeBuffer(pBuffer);
    }
    else
    {
     pBuffer->nLen=dwTrans;
     //写完成
     pThis->CompletedWriteDate(pBuffer,pContext);
     pThis->FreeBuffer(pBuffer);
    }
    break;
   }
  }
 }

 return 0;
}


BOOL IOCPServer::WriteDate(char *buf, int len, IOCPCONTEXT *pContext)
{
 IOCPBUFFER *pBuffer=this->AllocBuffer(BUFFER_SIZE);
 if(pBuffer!=NULL)
 {
  ::memcpy(pBuffer->buf,buf,len);
  if(this->PostSend(pBuffer,pContext))
  {
   return true;
  }
 }
 return false;
}

void IOCPServer::ShutDown()
{
 this->m_bShutDown=true;
 ::WaitForSingleObject(this->m_hListenThread,INFINITE);
 CloseHandle(this->m_hListenThread);
}


void IOCPServer::CompletedRecvDate(IOCPBUFFER* pBuffer, IOCPCONTEXT* pContext)  //用户自己重载
{
 
 
}

void IOCPServer::CompletedWriteDate(IOCPBUFFER *pBuffer, IOCPCONTEXT *pContext) //用户自己重载
{

}

void IOCPServer::ConnectionComplete(IOCPCONTEXT *pContext) //用户自己重载
{
 //printf("有新连接%s:%d/n",::inet_ntoa(pContext->addrRemote.sin_addr),::ntohs(pContext->addrRemote.sin_port));
}

void IOCPServer::DisConnection(IOCPCONTEXT *pContext)   //用户自己重载
{
 //printf("连接断开%s:%d/n",::inet_ntoa(pContext->addrRemote.sin_addr),::ntohs(pContext->addrRemote.sin_port)); 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值