类EasyIocp定义:
class EasyIocp
{
public:
EasyIocp();
~EasyIocp();
public:
static BOOL GetExtendSockFunc(SOCKET sock, LPVOID inBuff, DWORD inSize, LPVOID outBuff, DWORD outSize);
static int WinSockStart();
static int WinSockClean();
///函数:投递一个recv请求。
bool PostRecv(SOCKET transSock);
///函数:投递一个send请求。
bool PostSend(SOCKET transSock, char *data, int len);
bool start(sockaddr_in *bindAddr = NULL);
bool stop();
public:
inline HANDLE GetComletionPort()
{ return hCompPort_; }
void RemoveClient(SOCKET sock);
private:
void Construct();
void Destruct();
void InitThreadPool();
void FreeThreadPool();
void InitIocp();
void FreeIocp();
void InitListenSocket();
///函数:投递一个accpet请求。
void PostAccept(CompListenKey *listenKey, int index);
///函数:一个accept请求返回,等待处理。
void DoAccept(CompListenKey *listenKey, OVERLAPPED *ov, DWORD transBytes);
void DoAcceptWithData(CompListenKey *listenKey, int index, EasyIocpBuffer *iocpBuffer, sockaddr_in *serverAddr, sockaddr_in *clientAddr);
void DoAcceptWithoutData(CompListenKey *listenKey, int index, sockaddr_in *serverAddr, sockaddr_in *clientAddr);
///函数:投递一个recv请求。
bool PostRecv(CompTransmitKey *transKey, bool reset = true);
///函数:有数据到达。
void DoRecv(CompTransmitKey *transKey, DWORD transBytes);
///函数:投递一个send请求。
bool PostSend(CompTransmitKey *transKey);
///函数:有数据已发送。
void DoSend(CompTransmitKey *transKey, DWORD transBytes);
///函数:仅仅作为调试时调用。
void PushToDebug(CompTransmitKey *transKey);
private:
///线程池
TP_CALLBACK_ENVIRON tpCBE_;
PTP_WORK *ptpWorks_; //每个数组成员,标识一个回调函数
EasyIocpStruct::WORK_ARG *workArgs_; //回调函数参数
int worksNum_; //回调函数的数量
///函数:工人函数。
static void NTAPI TPCallBack(PTP_CALLBACK_INSTANCE Instance, PVOID pParam, PTP_WORK Work);
///函数:处理具体的业务。
static void DealCompletionPacket(EasyIocp *iocpModel, CompletionKey *compKey, LPOVERLAPPED pOv, DWORD transBytes);
static void ClearShutFlag();
static void SetShutFlag();
static bool IsShutDown();
static volatile long shutDownFlag_; //关闭标识
///IOCP
HANDLE hCompPort_;
sockaddr_in bindAddr_;
CompListenKey compListen_; //处理监听
EasyClients easyClients_; //处理连接的客户端
LPFN_ACCEPTEX funcAcceptEx_; //拓展函数
LPFN_GETACCEPTEXSOCKADDRS funcGetAcceptExSockAddrs_; //拓展函数
};
//
///类 CompletionKey ,虚基类作为socket与completion port关联时的key参数指针。
class CompletionKey
{
protected:
CompletionKey(EasyIocpKeyType keyType)
: keyType_(keyType)
, sock_(INVALID_SOCKET)
, operType_(operInvalid)
{}
public:
virtual CompletionKey* clone() = 0;
EasyIocpOper GetOperType() const
{ return operType_; }
void SetOperType(EasyIocpOper oper)
{ operType_ = oper; }
EasyIocpKeyType GetKeyType() const
{ return keyType_; }
SOCKET GetSocket() const
{ return sock_; }
void SetSocket(SOCKET sock)
{ sock_ = sock; }
void CloseSocket()
{ if(sock_ != INVALID_SOCKET) closesocket(sock_); }
protected:
SOCKET sock_;
EasyIocpOper operType_;
EasyIocpKeyType keyType_;
};
//
///类 CompListenKey ,作为listen socket与completion port关联时的key参数。
///由于工人线程函数有可能同时使用CompListenKey指针,注意多线程操作。
class CompListenKey : public CompletionKey
{
public:
CompListenKey();
public:
CompletionKey* clone();
int GetIndex(OVERLAPPED *ovAddr);
EasyIocpBuffer* GetOneBuffer(int index);
OVERLAPPED* GetOneOverlapped(int index);
SOCKET GetOneAcceptSock(int index);
void ClearOne(int index);
void Clear();
BOOL SetOneAcceptSock(int index, SOCKET sock);
private:
//下面数组的索引值由重叠结构标识
OVERLAPPED ovs_[EASYIOCP_ACCEPT_NUM]; //重叠结构,每投递一个请求对应一个重叠结构
SOCKET acceptSocks_[EASYIOCP_ACCEPT_NUM];
EasyIocpBuffer iocpBuffers_[EASYIOCP_ACCEPT_NUM];
};
//
///类 TransmitKey, 实际的收发数据的socket与completion key关联时的key参数。
class CompTransmitKey : public CompletionKey
{
public:
CompTransmitKey();
public:
CompletionKey* clone();
void SetServerAddr(sockaddr_in *addr);
void SetClientAddr(sockaddr_in *addr);
void GetBothAddr(sockaddr_in *server, sockaddr_in *client);
EasyIocpBuffer* GetBuffer();
OVERLAPPED* GetOverlapped();
private:
OVERLAPPED ov_;
EasyIocpBuffer iocpBuffer_;
sockaddr_in serverAddr_; //建立连接时服务端地址
sockaddr_in clientAddr_; //建立连接时客户端地址
};
类EasyIocpBuffer,记录传输的数据。
class EasyIocpBuffer
{
public:
EasyIocpBuffer();
///函数:赋值操作符,仅仅copy缓冲区数据。
EasyIocpBuffer& operator=(const EasyIocpBuffer& iocpBuffer);
public:
void Reset();
///函数:有新的数据发送或者接收时,先调用AddTransBytes函数累加,然后调用IsTransComplete函数查看是否传输完毕。
DWORD AddTransBytes(DWORD transBytes);
///函数:数据接收是否完整。数据由 消息头+消息本身 两部分组成。消息头固定为 sizeof(LONG32)字节表示数据的字节数。
bool IsTransComplete();
///函数:返回已经传输的字节数。
DWORD GetTransBytes();
///函数:获取WSABuff。
WSABUF* GetWSABuf();
///函数:获取实际数据的字节数。
DWORD GetBodySize();
///函数:获取实际的消息,不包括消息头。
DWORD GetBody(char *data, DWORD len);
///函数:设置发送的数据。
bool SetBody(char *data, DWORD len);
public:
static const BYTE headerSize; //消息头的大小,固定为 sizeof(ULONG32) 字节
private:
DWORD transmitedBytes_; //已经传送的字节数,包括消息头
DWORD totalBytes_; //消息本身的字节数,不包括消息头
WSABUF wsaBuf_;
char buffer_[EASYIOCP_MAX_BUFF]; //缓冲区,存放消息头+消息本身
};