//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));
}