123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #pragma once
- #include "Protocol.h"
- #define CONNECTING_STATE 0
- #define READING_STATE 1
- #define WRITING_STATE 2
- #define INSTANCES 4
- #define PIPE_TIMEOUT 5000
- #define BUFSIZE 4096
- // 命名管道在完成端口上投递的I/O操作的类型
- typedef enum _OPERATION_TYPE
- {
- OP_ACCEPT, // Accept操作;
- OP_SEND, // 发送操作
- OP_RECV, // 接收操作
- OP_MAX // 上限;
- } OPERATION_TYPE;
- extern void dprintf(TCHAR* pszStr, ...);
- // 单个IO请求;
- typedef struct _PER_IO_CONTEXT
- {
- OVERLAPPED m_Overlapped;
- HANDLE m_PipeAccept;
- OPERATION_TYPE m_OpType;
- // 接收客户端的消息;
- BYTE szBuffer[BUFSIZE];
- DWORD dwBufferLine;
- // 发送给客户的消息;
- //TCHAR chReply[BUFSIZE];
- //DWORD cbToWrite;
- // 管道状态;
- //DWORD dwState;
- // IO是否在等待;
- //BOOL fPendingIO;
- // 创建写IO;
- _PER_IO_CONTEXT *pWriteIoContext;
-
- // 初始化
- _PER_IO_CONTEXT()
- {
- ZeroMemory(&m_Overlapped, sizeof(m_Overlapped));
- ZeroMemory(szBuffer, BUFSIZE);
- //ZeroMemory(chReply, BUFSIZE);
- m_PipeAccept = INVALID_HANDLE_VALUE;
- m_OpType = OP_ACCEPT;
- pWriteIoContext = NULL;
- //fPendingIO = FALSE;
- //dwState = 0;
- }
- // 释放掉句柄
- ~_PER_IO_CONTEXT()
- {
- if (m_PipeAccept != INVALID_HANDLE_VALUE)
- {
- //CloseHandle(m_PipeAccept);// 此处不能CloseHandle,因为m_PipeAccept在PER_PIPE_CONTEXT中已释放;
- m_PipeAccept = INVALID_HANDLE_VALUE;
- }
- if ( pWriteIoContext )
- delete pWriteIoContext;
- pWriteIoContext = NULL;
- }
- // 重置缓冲区内容
- void ResetBuffer()
- {
- dprintf(_T("ResetBuffer:%p"), &m_Overlapped);
- ZeroMemory(szBuffer, BUFSIZE);
- //ZeroMemory(chReply, BUFSIZE);
- }
- } PER_IO_CONTEXT, *PPER_IO_CONTEXT;
- typedef struct _PER_PIPE_CONTEXT
- {
- HANDLE m_hPipe;
- // 客户端进程PID;
- DWORD dwProcessId;
- // 客户端进程窗口名称;
- TCHAR szClientName[255];
- // 该Pipe下的所有IO事件;
- CArray<_PER_IO_CONTEXT*> m_arrayIoContext;
- _PER_PIPE_CONTEXT()
- {
- m_hPipe = INVALID_HANDLE_VALUE;
- dwProcessId = 0;
- memset(szClientName, 0, sizeof(TCHAR)*255);
- }
- ~_PER_PIPE_CONTEXT()
- {
- if ( m_hPipe != INVALID_HANDLE_VALUE )
- {
- CloseHandle(m_hPipe);
- m_hPipe = INVALID_HANDLE_VALUE;
- // 释放掉所有的IO上下文数据
- for( int i=0; i<m_arrayIoContext.GetCount(); i++ )
- {
- delete m_arrayIoContext.GetAt(i);
- }
- m_arrayIoContext.RemoveAll();
- }
- }
- // 设置客户端信息;
- void SetClientInfo(DWORD dwClientId, LPCTSTR lpszClientName)
- {
- dwProcessId = dwClientId;
- _stprintf_s(szClientName, _T("%s"), lpszClientName == NULL ? _T("Null") : lpszClientName);
- }
- // 获取一个新的IoContext
- _PER_IO_CONTEXT* GetNewIoContext()
- {
- _PER_IO_CONTEXT* p = new _PER_IO_CONTEXT;
- m_arrayIoContext.Add( p );
- return p;
- }
- // 从数组中移除一个指定的IoContext
- void RemoveContext( _PER_IO_CONTEXT* pContext )
- {
- ASSERT( pContext!=NULL );
- for( int i=0; i<m_arrayIoContext.GetCount(); i++ )
- {
- if( pContext == m_arrayIoContext.GetAt(i) )
- {
- if ( pContext->pWriteIoContext )
- delete pContext->pWriteIoContext;
- delete pContext;
- pContext = NULL;
- m_arrayIoContext.RemoveAt(i);
- break;
- }
- }
- }
- }PER_PIPE_CONTEXT, *PPER_PIPE_CONTEXT;
- // 回调客户端接入时;
- typedef BOOL(CALLBACK *OnGoCallback)(DATAHEADER *pHeader, MSG_INFO* pMsg);
- // 回调客户端接入时;
- typedef BOOL(CALLBACK *OnConnectCallback)(DATAHEADER *pHeader, MSG_INFO* pMsg);
- // 回调客户端断开时;
- typedef BOOL(CALLBACK* OnDisconnectCallback)(PER_IO_CONTEXT* pIoContext);
- // 回调客户端消息到来时;
- typedef BOOL(CALLBACK *OnReciveCallback)(PER_PIPE_CONTEXT *pPipeContext, PER_IO_CONTEXT *pIoContext);
- // 工作者线程的线程参数
- class CIOCPPipe;
- typedef struct _tagThreadParams_WORKER
- {
- CIOCPPipe *pIOCPModel; // 类指针,用于调用类中的函数
- int nThreadNo; // 线程编号
- } THREADPARAMS_WORKER, *PTHREADPARAM_WORKER;
- // CIOCPPipe类
- class CIOCPPipe
- {
- public:
- CIOCPPipe(void);
- ~CIOCPPipe(void);
- public:
- // 启动服务器
- bool Start();
- // 停止服务器
- void Stop();
- // 设置主界面的指针,用于调用显示信息到界面中
- void SetMainDlg(CDialog *p) { m_pMain = p; }
- // 向客户端发送消息;
- BOOL SendPackage(DATAHEADER &header, MSG_INFO &msg);
- // SetCallback;
- static void SetCallBack(LPVOID lpOnConnect, LPVOID lpOnDisconnect, LPVOID lpOnGo, LPVOID lpOnRecive)
- {
- if ( lpOnConnectCallback == NULL )
- lpOnConnectCallback = (OnConnectCallback)lpOnConnect;
- if ( lpOnDisconnectCallback == NULL )
- lpOnDisconnectCallback = (OnDisconnectCallback)lpOnDisconnect;
- if ( lpOnGoCallback == NULL )
- lpOnGoCallback = (OnGoCallback)lpOnGo;
- if ( lpOnReciveCallback == NULL )
- lpOnReciveCallback = (OnReciveCallback)lpOnRecive;
- }
- protected:
- // 初始化IOCP
- bool InitIOCP();
- // 最后释放资源
- void DeInitialize();
- // 投递Accept请求
- bool PostAccept();
- // 投递接收数据请求
- bool PostRecv(PER_IO_CONTEXT *pIoContext);
- // 在有客户端连入的时候,进行处理
- bool DoAccpet(PER_PIPE_CONTEXT *pPipeContext, PER_IO_CONTEXT *pIoContext);
- // 在有接收的数据到达的时候,进行处理
- bool DoRecv(PER_PIPE_CONTEXT *pPipeContext, PER_IO_CONTEXT *pIoContext);
- // 将客户端的相关信息存储到数组中
- void AddToContextList(PER_PIPE_CONTEXT *pPipeContext);
- // 将客户端的信息从数组中移除
- void RemoveContext(PER_PIPE_CONTEXT *pPipeContext);
- // 清空客户端信息
- void ClearContextList();
- // 将句柄绑定到完成端口中
- bool AssociateWithIOCP(PER_IO_CONTEXT *pIoContext);
- // 处理完成端口上的错误
- bool HandleError(PER_PIPE_CONTEXT *pPipeContext, const DWORD &dwErr);
- // 线程函数,为IOCP请求服务的工作者线程
- static DWORD WINAPI _WorkerThread(LPVOID lpParam);
- // 获得本机的处理器数量
- int GetNoOfProcessors();
- // 判断客户端Socket是否已经断开
- bool IsSocketAlive(SOCKET s);
- // 在主界面中显示信息
- void ShowMessage(const CString szFormat, ...) const;
- // 处理返回值;
- void RecvProcess(PER_PIPE_CONTEXT* pPipeContext, PER_IO_CONTEXT* pIoContext);
- private:
- static OnConnectCallback lpOnConnectCallback;
- static OnDisconnectCallback lpOnDisconnectCallback;
- static OnGoCallback lpOnGoCallback;
- static OnReciveCallback lpOnReciveCallback;
- HANDLE m_hShutdownEvent; // 用来通知线程系统退出的事件,为了能够更好的退出线程
- HANDLE m_hIOCompletionPort; // 完成端口的句柄
- HANDLE *m_phWorkerThreads; // 工作者线程的句柄指针
- int m_nThreads; // 生成的线程数量
- CDialog *m_pMain; // 主界面的界面指针,用于在主界面中显示消息
- CRITICAL_SECTION m_csContextList; // 用于Worker线程同步的互斥量
- CArray<PER_PIPE_CONTEXT *> m_arrayClientContext; // 客户端Socket的Context信息
- };
|