class Iocp //完成端口 功能類 class IocpMemoryManager //此類提供IOCP 內存的管理 [cpp] #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); //工作線程 }; [cpp] //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; };