#include "StdAfx.h"
#include ".\iocpserver.h"
#define OP_ACCEPT 1
#define OP_WRITE 2
#define OP_READ 3
CIOCPServer::CIOCPServer(void)
{//列表
m_pFreeBufferList=NULL;
m_pFreeContextList=NULL;
m_pPendingAccepts=NULL;
m_pConnectionList=NULL;
m_nFreeBufferCount=0;
m_nFreeContextCount=0;
m_nPendingAcceptCount=0;
m_nCurrentConnection=0;
::InitializeCriticalSection(&m_FreeBufferListLock);
::InitializeCriticalSection(&m_FreeContextListLock);
::InitializeCriticalSection(&m_PendingAcceptsLock);
::InitializeCriticalSection(&m_ConnectionListLock);
//Accept请求
m_hAcceptEvent=::CreateEvent(NULL,FALSE,FALSE,NULL);
m_hRepostEvent=::CreateEvent(NULL,FALSE,FALSE,NULL);
m_nRepostCount=0;
m_nPort=4567;
m_nInitialAccepts=10;
m_nInitialReads=4;
m_nMaxAccepts=100;
m_nMaxSends=20;
m_nMaxFreeBuffers=200;
m_nMaxFreeContexts=100;
m_nMaxConnections=2000;
m_hListenThread=NULL;
m_hCompletion=NULL;
m_sListen=INVALID_SOCKET;
m_lpfnAcceptEx=NULL;
m_lpfnGetAcceptExSockaddrs=NULL;
m_bShutDown=FALSE;
m_bServerStarted=FALSE;
//初始化WSA_32.DLL
WSADATA wsaData;
WORD sockVersion=MAKEWORD(2,2);
::WSAStartup(sockVersion,&wsaData);
}
CIOCPServer::~CIOCPServer(void)
{
Shutdown();
if(m_sListen!=INVALID_SOCKET)
::closesocket(m_sListen);
if(m_hListenThread!=NULL)
::CloseHandle(m_hListenThread);
::CloseHandle(m_hRepostEvent);
::CloseHandle(m_hAcceptEvent);
::DeleteCriticalSection(&m_FreeBufferListLock);
::DeleteCriticalSection(&m_FreeContextListLock);
::DeleteCriticalSection(&m_PendingAcceptsLock);
::DeleteCriticalSection(&m_ConnectionListLock);
::WSACleanup();
}
/*
*功能:申请内存空间
*参数:I/O操作所使用的缓冲区长度
*返回值:I/O操作的指针
*/
CIOCPBuffer *CIOCPServer::AllocateBuffer(int nLen)
{
CIOCPBuffer *pBuffer=NULL;
if(nLen>BUFFER_SIZE)
return NULL;
//为缓冲区对象申请内存
::EnterCriticalSection(&m_FreeBufferListLock);
if(m_pFreeBufferList==NULL)//内存池为空,申请新的内存
{
pBuffer=(CIOCPBuffer *)::HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,sizeof(CIOCPBuffer)+BUFFER_SIZE);
}
else
{
pBuffer=m_pFreeBufferList;
m_pFreeBufferList=m_pFreeBufferList->pNext;
pBuffer->pNext=NULL;
m_nFreeBufferCount--;
}
::LeaveCriticalSection(&m_FreeBufferListLock);
//初始化新的缓冲区对象
if(pBuffer!=NULL)
{
pBuffer->buff=(char *)(pBuffer+1);
pBuffer->nLen=nLen;
}
return pBuffer;
}
void CIOCPServer::ReleaseBuffer(CIOCPBuffer *pBuffer)
{
::EnterCriticalSection(&m_FreeBufferListLock);
if(m_nFreeBufferCount<=m_nMaxFreeBuffers)//将要释放的内存添加到空闲列表中
{
memset(pBuffer,0,sizeof(CIOCPBuffer)+BUFFER_SIZE);
pBuffer->pNext=m_pFreeBufferList;
m_pFreeBufferList=pBuffer;
m_nFreeBufferCount++;
}
else//已经达到最大值真正的释放内存
{
::HeapFree(::GetProcessHeap(),0,pBuffer);
}
::LeaveCriticalSection(&m_FreeBufferListLock);
}
//孙亚新补充
//申请上下文
CIOCPContext *CIOCPServer::AllocateContext(SOCKET s)
{
CIOCPContext *pContext=NULL;
::EnterCriticalSection(&m_FreeContextListLock);
if(m_pFreeContextList==NULL)//句柄上下文链表为空,申请新的句柄上下文
{
pContext=(CIOCPContext *)::HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,sizeof(CIOCPContext)+sizeof(CIOCPBuffer));
}
else
{
pContext=m_pFreeContextList;
m_pFreeContextList=m_pFreeContextList->pNext;
pContext->pNext=NULL;
m_nFreeContextCount--;
}
::LeaveCriticalSection(&m_FreeContextListLock);
if(pContext!=NULL)
{
pContext->pOutOfOrderReads=(CIOCPBuffer *)(pContext+1);
pContext->pOutOfOrderReads->buff=NULL;
pContext->s=s;
}
return pContext;
}
void CIOCPServer::ReleaseContext(CIOCPContext *pContext)
{
if(pContext->s!=INVALID_SOCKET)
::closesocket(pContext->s);
//首先释放(如果有的话)此套接字上的没有按顺序完成的读I/0的缓冲区
CIOCPBuffer *pNext;
while(pContext->pOutOfOrderReads!=NULL)
{
pNext=pContext->pOutOfOrderReads->pNext;
ReleaseBuffer(pContext->pOutOfOrderReads);
pContext->pOutOfOrderReads=pNext;
}
::EnterCriticalSection(&m_FreeContextListLock);
if(m_nFreeContextCount<=m_nMaxFreeContexts)//添加到空闲列表
{
CRITICAL_SECTION cstmp=pContext->Lock;//先将关键代码段变量保存在一个临时变量中
memset(pContext,0,sizeof(CIOCPContext));//将要释放的上下问对象初始化0
//将要释放的上下文对象添加到空闲列表表头
pContext->Lock=cstmp;
pContext->pNext=m_pFreeContextList;
m_pFreeContextList=pContext;
m_nFreeContextCount++;//更新记数
}
else
{
::DeleteCriticalSection(&pContext->Lock);
::HeapFree(::GetProcessHeap(),0,pContext);
}
}
//服务器关闭时释放内存池占用的地方实现方法便历m_pFreeBufferList
//孙亚新补充
void CIOCPServer::FreeBuffers()
{
if(m_pFreeBufferList!=NULL)
{
CIOCPBuffer *pBufferList=m_pFreeBufferList;
CIOCPBuffer *pPreBufferList=m_pFreeBufferList;
while(pBufferList->pNext!=NULL)
{
pBufferList=pBufferList->pNext;
::HeapFree(::GetProcessHeap(),0,pPreBufferList);
pPreBufferList=pBufferList;
}
}
}
//服务器关闭时释放内存池占用实现方法遍历m_pFreeContextList
//孙亚新补充
void CIOCPServer::FreeContexts()
{
if(m_pConnectionList!=NULL)
{
CIOCPContext *pContextList=m_pConnectionList;
CIOCPContext *pPreContextList=m_pConnectionList;
while(pContextList->pNext!=NULL)
{
pContextList=pContextList->pNext;
::HeapFree(::GetProcessHeap(),0,pPreContextList);
pPreContextList=pContextList;
}
}
}
//成员变量m_pConnectionList指向课户连接列表既描述所有连
//接的CIOCPContext
//对象组成的表
//向表中添加一个CIOCPContext对象。如果已经达到了最大的
//连接数量,函数返回FALSE
//孙亚新补充
BOOL CIOCPServer::AddAConnection(CIOCPContext *pContext)
{
if(m_nCurrentConnection<=m_nMaxConnections)
{
pContext->pNext=m_pConnectionList;
m_pConnectionList=pContext;
return TRUE;
}
return FALSE;
}
//关闭指定的客户连接,他先从连接;列表中移除要关闭的连接
//然后再关闭客户套接字
//孙亚新补充
void CIOCPServer::CloseAConnection(CIOCPContext *pContext)
{
CIOCPContext *pZanShiContext;
CIOCPContext *pPreContext;
pZanShiContext=m_pConnectionList;
pPreContext=m_pConnectionList;
::WaitForSingleObject(m_hCompletion,INFINITE);
if(pZanShiContext==pContext)//判断是不是表头
m_pConnectionList=pContext->pNext;
while(pZanShiContext->pNext!=pContext&&pZanShiContext->pNext!=NULL)//如果不是的话把指针依次往后移
{
pZanShiContext=pZanShiContext->pNext;
}
pPreContext=pZanShiContext->pNext;
pZanShiContext->pNext=pZanShiContext->pNext->pNext;
Rele