CIOCPServer类使用了现金的IOCP技术,它可以非常高效的为大量客户提供服务。 CIOCPServer类接收到用户的启动命令之后,首先创建监听线程,再由监听线程创建工作线程。服务器启动期间,监听线程一直运行,为I/o工作线程提供服务。
#define BUFFER_SIZE 1024*4 //I/OQ请求的缓冲区大小
#define MAX_THREAD 2 //I/O服务线程的数量
class CIOCPServer
{
public:
CIOCPServer();
~CIOCPServer();
//开始服务
BOOL Start(int nPort=4567,int nMaxConnections=2000,int nMaxFreeBuffers=200,int nMaxFreeContexts=100,int nInitialReads=4);
//停止服务
void shutdown();
//关闭一个连接和关闭所有连接
void CloseAConnection(CIOCPContext *pContext);
void CloseAllConnections();
//取得当前的连接数量
ULONG GetCurrentConnection()
{
return m_nCurrentConnection;
}
//向指定客户发送文本
BOOL SendText(CIOCPContext *pContext,char *pszText,int nLen);
protected:
//申请和释放缓冲区对象
CIOCPBuffer *AllocateBuffer(int nLen);
void RealeaseBuffer(CIOCPBuffer *pBuffer);
//申请和释放套接字上下文
CIOCPContext *AllocateContext(SOCKET s);
void RealeaseContext(CIOCPContext *pContext);
//释放空闲缓冲区对象列表和空闲上下文对象列表
void FreeBuffers();
void FreeContexts();
//向连接列表中添加一个连接
BOOL AddAConnection(CIOCPContext *pContext);
//插入和移除未决的接受请求
BOOL InsertPendingAccept(CIOCPBuffer *pBuffer);
BOOL RemovePendingBuffer(CIOCPBuffer *pBuffer);
//取得下一个要读取的
CIOCPBuffer *GetNextReadBuffer(CIOCPCoNTEXT *pContext,CIOCPBuffer *pBuffer);
//t投递接受I/O、发生I/O、接收I/O
BOOL PostAccept(CIOCPBuffer *pBuffer);
BOOL PostSend(CIOCPContext *pContext,CIOCPBuffer *pBuffer);
BOOL PostRecv(CIOCPContext *pContext,CIOCPBuffer *pBuffer);
void HandleIO(DWORD dwKey,CIOCPBuffer *pBuffer,DWORD dwTrans,int nError);
//事件通知函数
//建立一个新的连接
virtual void OnConnectionEstablished(CIOCPContext *pContext,CIOCPBuffer *pBuffer);
//一个连接关闭
virtual void OnConnectionClosing(CIOCPContext *pContext,CIOCPBuffer *pBuffer);
//在一个连接上发生了错误
virtual void OnConnectionError(CIOCPContext *pContext,CIOCPBuffer *pContext,int nError);
//一个连接上的读操作完成
virtual void OnReadCompleted(CIOCPContext *pContext,CIOCPBuffer *pBuffer);
protected:
//记录空闲结构信息
CIOCPBuffer *m_pFreeBufferList;
CIOCPContext *m_pFreeContextList
int m_nFreeBufferCount;
int m_nFreeContextCount;
CRITICAL_SECTION m_FreeBufferListLock;
CRITICAL_SECTION m_FreeContextListLock;
//记录抛出的Accept请求
CIOCPBuffer *m_nPendingAccepts ;//抛出请求列表
long m_nPendingAcceptCount;
CRITICAL_SECTION m_PendingAcceptsLock;
//记录连接列表
CIOCPContext *m_pConnectionList;
int m_nCurrentConnection;
CRITICAL_SECTION m_ConnectionListLock;
//用于投递Accept请求
HANDLE m_hAcceptEvent;
HANDLE m_hRepostEvent;
LONG m_nRepostCount;
int m_nPort;
int m_nInitialAccepts;
int m_nInitialReads;
int m_nMaxAccepts;
int m_nMaxSends;
int m_nMaxFreeBuffers;
int m_nMaxFreeContexts;
int m_nMaxConnections;
HANDLE m_hListenThread;//监听线程
HANDLE m_nCompletion;//完成端口句柄
SOCKET m_sListen;//监听套接字句柄
LPFN_ACCEPTEXSOCKADDRS m_lpfnGetAcceptExSockaddrs;//GetAcceptExSockaddrs函数地址
BOOL m_bShutDown;//用于通知监听线程退出
BOOL m_hServerStarted;//记录服务是否启动
private:
static DWORD WINAPI_ListenThreadProc(LPVOID lpParam);
static DWORD WINAPI_WorkerThreadProc(LPVOID lpParam);
}
类的构造函数要初始化各个成员变量,要对所有的关键代码段变量调用IntializeCriticalSection函数,为两个事件对象句柄m_HAcceptEvent和m_hRepostEvent调用CreateEvent函数,还要调用WSAStartup函数初始化Winsock库。类的析构函数则要释放各种资源。
#include "CIOCPServer.h"
CIOCPServer::CIOCPServer()
{
m_pFreeBufferList=NULL;
m_pFreeContextList=NULL;
m_nPendingAccepts=NULL;
m_pConnectionAccepts=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;
.....
......
}
CIOCPServer::~CIOCPServer()
{
.....
....
}