文章转自王牌软件----
class Iocp //完成端口 功能类
class IocpMemoryManager //此类提供IOCP 内存的管理
//Iocp.h
#pragma once
#include "IocpMemoryManager.h"
#include <windows.h>
#define MAXWORKERTHREADS 2
//iocp类封装
classCIocp
{
public:
CIocp(void);
~CIocp(void);
boolStartServer(intnPort = 4568, intnMaxConnections = 2000);//开始服务 监听端口,最大的连接数
boolReStartServer(); //重启服务
boolStopServer(); //停止服务
intGetCurrentConnection(); //得到当前的连接数
boolSendText(CIOCPContext *pContext, char*pszText, intnLen);//发送数据给客户端
char* GetCustomLastError(); //获取最后的错误信息
protected:
// 事件通知函数
virtualvoid OnConnectionEstablished(CIOCPContext *pContext, CIOCPBuffer *pBuffer) = 0; // 建立了一个新的连接
virtualvoid OnConnectionClosing(CIOCPContext *pContext, CIOCPBuffer *pBuffer) = 0; // 一个连接关闭
virtualvoid OnConnectionError(CIOCPContext *pContext, CIOCPBuffer *pBuffer, intnError) = 0;// 在一个连接上发生了错误
virtualvoid OnReadCompleted(CIOCPContext *pContext, CIOCPBuffer *pBuffer) = 0; // 一个连接上的读操作完成
virtualvoid OnWriteCompleted(CIOCPContext *pContext, CIOCPBuffer *pBuffer) = 0; // 一个连接上的写操作完成
private:
IocpMemoryManager* m_pIocpMemoryManager;//此类提供IOCP 内存的管理
boolm_bServerStarted; //服务是否已经启动
intm_nPort; // 服务器监听的端口
intm_nInitialAccepts; //初始化投递的接受请求数
intm_nInitialReads; //初始化投递Accept数
intm_nMaxAccepts; //最大接受数
intm_nMaxSends; //单套接字最大发送数
intm_nMaxListenCount; //最大的监听数
intm_nMaxWorkerThreads; //最大工作线程数
char* m_pcaErrorMessage; //错误信息 取得最后一个错误信息
//Event
HANDLEm_hAcceptEvent; // 用于投递Accept请求
HANDLEm_hRepostEvent;
LONGm_nRepostCount;
//套接字信息
HANDLEm_hListenThread; // 监听线程
HANDLEm_hCompletion; // 完成端口句柄
SOCKET m_sListen; // 监听套节字句柄
LPFN_ACCEPTEX m_lpfnAcceptEx; // AcceptEx函数地址
LPFN_GETACCEPTEXSOCKADDRS m_lpfnGetAcceptExSockaddrs; // GetAcceptExSockaddrs函数地址
private:
boolDoWSAStartup(); //初始化 socket库
voidInitData(); //初始化数据
voidInitEvent(); //初始化Event
boolCreateIocpPort(); //创建完成端口
voidSetCustomLastError(char* error); //设置错误
boolPostAccept(CIOCPBuffer *pBuffer); // 投递接受I/O
boolPostSend(CIOCPContext *pContext, CIOCPBuffer *pBuffer); // 投递发送I/O
boolPostRecv(CIOCPContext *pContext, CIOCPBuffer *pBuffer); // 投递接收I/O
voidHandleIO(DWORDdwKey, CIOCPBuffer *pBuffer, DWORDdwTrans, intnError); //总请求处理
voidHandleAccept(CIOCPBuffer *pBuffer, DWORDdwTrans); //处理接收请求
voidHandleRead(CIOCPContext *pContext, CIOCPBuffer *pBuffer, DWORDdwTrans); //处理读请求
voidHandleWrite(CIOCPContext *pContext, CIOCPBuffer *pBuffer, DWORDdwTrans);//处理写请求
staticDWORD WINAPI _ListenThreadProc(LPVOIDlpParam); //监听线程
staticDWORD WINAPI _WorkerThreadProc(LPVOIDlpParam); //工作线程
};
//IocpMemoryManager.h
#pragma once
#include <winsock2.h>
#include <Mswsock.h>
#include <list>
#include <iostream>
usingnamespace std;
//此类提供IOCP 内存的管理
#define BUFFER_SIZE 1024*4 // I/O请求的缓冲区大小 单次发送最大 4096
// 这是per-I/O数据。它包含了在套节字上处理I/O操作的必要信息
classCIOCPBuffer
{
public:
CIOCPBuffer();
~CIOCPBuffer();
boolisUsed;
WSAOVERLAPPED ol;
SOCKET sClient; // AcceptEx接收的客户方套节字
char*buff; // I/O操作使用的缓冲区
intnLen; // buff缓冲区(使用的)大小
ULONGnSequenceNumber; // 此I/O的序列号
intnOperation; // 操作类型
#define OP_ACCEPT 1
#define OP_WRITE 2
#define OP_READ 3
};
// 这是per-Handle数据。它包含了一个套节字的信息
classCIOCPContext
{
public:
CIOCPContext();
~CIOCPContext();
boolisUsed;
SOCKET s; // 套节字句柄
SOCKADDR_IN addrLocal; // 连接的本地地址
SOCKADDR_IN addrRemote; // 连接的远程地址
boolbClosing; // 套节字是否关闭
intnOutstandingRecv; // 此套节字上抛出的重叠操作的数量
intnOutstandingSend;
ULONGnReadSequence; // 安排给接收的下一个序列号
ULONGnCurrentReadSequence; // 当前要读的序列号
list<CIOCPBuffer*> pOutOfOrderReadsList; // 记录没有按顺序完成的读I/O
CRITICAL_SECTION Lock; // 保护这个结构
};
classIocpMemoryManager
{
public:
IocpMemoryManager(void);
~IocpMemoryManager(void);
staticIocpMemoryManager* GetInstence();
intm_nMaxFreeBuffers; //最大的空闲Buffer
intm_nMaxFreeContexts; //最大的空闲Contexts
intm_nMaxConnections; //最大的连接数
intGetContextListCount(){returnm_contextList.size();}
//Accept 操作
boolInsertAPendingAccept(CIOCPBuffer *pBuffer);
boolRemoveAPendingAccept(CIOCPBuffer *pBuffer);
intGetPendingAcceptCount();
//buffer 操作
CIOCPBuffer* AllocateBuffer(intnLen = BUFFER_SIZE);//buffer 申请
voidReleaseABuffer(CIOCPBuffer *pBuffer); //buffer 释放
CIOCPBuffer* GetANoUseBuffer(); //获取一个空闲的buffer
intGetFreeBuffersCount(); //获取空闲的Buffer的数目
//Contexts 操作
CIOCPContext* AllocateContext(constSOCKET& sClient); //Contexts 申请
voidReleaseAContext(CIOCPContext *pBuffer); //Contexts 释放
CIOCPContext* GetANoUseContexts(); //获取一个空闲的Contexts
intGetFreeContextsCount(); 获取空闲的Contexts的数目
voidCloseAConnection(CIOCPContext *pContext);
voidCloseAllConnections(); //关闭所有的socket 但不FreeContexts();
voidFreeBuffers(); //清空所有Buffers
voidFreeContexts(); //清空所有Contexts
// 取得下一个要读取的
CIOCPBuffer *GetNextReadBuffer(CIOCPContext *pContext, CIOCPBuffer *pBuffer);
//获取工作线程最大数 = CPU个数*2{最佳}
intGetMaxWorkerThreadCount();
voidHandlePendingAcceptTimeOut();
private:
list<CIOCPBuffer*> m_bufferList; //统一管理 【管理所有申请的buffer】
list<CIOCPContext*> m_contextList;//统一管理 【管理所有申请的context】
list<CIOCPBuffer*> m_pPendingAcceptsList;
CRITICAL_SECTION m_FreeBufferListLock;
CRITICAL_SECTION m_FreeContextListLock;
CRITICAL_SECTION m_PendingAcceptsLock;
CRITICAL_SECTION m_ConnectionListLock;
};