www.pudn.com > 2003090514065121890.zip > spRmtMonitor.h
#ifndef __RMT_MONITOR_H_
#define __RMT_MONITOR_H_
#include "spSocketServer.h"
namespace spBase
{
class CRemoteHandlerData;
class CRemoteMonitorManager;
class CRemoteHelper;
//回调函数定义
//验证用户身份的回调函数
typedef BOOL (*PVERIFYUSER)(LPCSTR pszUser,LPCSTR pszPwd);
//用户需要提供的监控处理回调函数
typedef void (*PMONITORHANDLER)(CRemoteHelper* pHelper,SOCKET sockComm);
/*
远程监控管理类
*/
class CRemoteMonitorManager
{
public:
CRemoteMonitorManager(LPCSTR pszSvrDesc,PMONITORHANDLER pHandler,LPCSTR pszSvrName="defrmm",COutputDisplay* pOutput=NULL,LPCSTR pszLocalIP=NULL,int iLocalPort=18189,int iMaxMsg=100);
~CRemoteMonitorManager();
public:// start & stop
BOOL StartMonitor(void);
BOOL StopMonitor(void);
void GetSvrDesc(CString& szDesc){szDesc=m_szSvrDescription;};
BOOL IsGoon(void){return m_fGoon;};
public:// message manipulate
//将待发送消息添加到列表中,添加到尾部
void PushMsg(LPCSTR pszMsg);
//将紧急消息添加到列表中,添加到头部
void PushUrgentMsg(LPCSTR pszMsg);
//由监控线程将数据提供在主控制台上显示
//fToOtherMonitor 是否发送到其他监控窗口
void OutputToMainConsole(LPCSTR pszMsg,BOOL fToAllMonitor=FALSE,BOOL fUrgent=FALSE);
void OutputToMainConsole(COutputDisplay::ErrorLevel eLevel,LPCSTR pszMsg,BOOL fToAllMonitor=FALSE,BOOL fUrgent=FALSE);
public://MonitorList manipulate
CRemoteHandlerData* AddMonitorData(LPCSTR pszDesc,int iSeq);
BOOL DelMonitorData(int iSeq);
public:// thread
//监听线程
static DWORD __stdcall ListenThread(void* pD);
//将主消息区中数据拷贝到所有连接上的客户消息区,并删除主消息区中数据
static DWORD __stdcall MsgCopyThread(void* pD);
//客户连接处理线程,实际上会在内部调用客户提供的处理函数:m_pfnMonitor
static DWORD __stdcall MonitorWrapThread(void* pD);
protected:
//取出信息列表,并重新申请新的列表对象
//如果当前列表为空则返回NULL
CStringList* ResetMsgList(void);
//删除队列中过多的消息,消息数量由 m_iMaxMsg定义
void DelOverfullMsg(int iCount=1);
protected:
CString m_szSvrDescription;//服务器名称
CRWAccessLock *m_plockMsg;
CStringList *m_plistMsg;
CRWAccessLock *m_plockHandlerData;
CList *m_plistHandlerData;
COutputDisplay *m_pOutput;//向外界传递信息的对象,参考 服务器模式手册.doc & spServer.h
int m_iMaxMsg;//在信息列表中最多保存的信息数量
BOOL m_fGoon;//是否继续的标记
CString m_szLocalIP;
int m_iLocalPort;
PMONITORHANDLER m_pfnMonitor; //处理函数入口
SOCKET m_sockListen;
protected:
HANDLE m_hListenThread;
HANDLE m_hMsgCopyThread;//守护线程句柄,将信息列表中的数据分别拷贝到单个监控线程所对应的数据空间
};
/*
CRemoteHandlerData 保存当前监控连接的相关参数
*/
class CRemoteHandlerData
{
public:
CRemoteHandlerData(LPCSTR pszDesc,int iSeq,SOCKET sComm,int iMaxMsg=100);
~CRemoteHandlerData();
public:
//将待发送消息添加到列表中,添加到尾部
void PushMsg(LPCSTR pszMsg);
//将紧急消息添加到列表中,添加到头部
void PushUrgentMsg(LPCSTR pszMsg);
//从列表中取出待发送消息,从头部取出
BOOL PopMsg(CString &szGet);
//将一个列表全部加到消息列表中
BOOL AddMsgList(CStringList* pList);
//删除队列中过多的消息,消息数量由 m_iMaxMsg定义
void DelOverfullMsg(int iCount=1);
//得到连接序号ID
int GetSeqID(void){return m_iSeqID;};
//得到和设置线程句柄
HANDLE GetThreadHandle(void){return m_hHandlerThread;};
void SetThreadHandle(HANDLE hThread){m_hHandlerThread = hThread;};
//得到通信用的SOCKET
SOCKET GetSocketCopy(void){return m_sockCommCopy;};
protected:
CRWAccessLock *m_plockMsg;//对消息列表的锁
CStringList *m_plistMsg;//消息列表
int m_iMaxMsg;//最多保留的消息数量
int m_iSeqID;//连接序号,用于标记唯一的一个连接对象
CString m_szConnDesc;//连接描述
HANDLE m_hHandlerThread;//提供监控服务的线程句柄 CRemoteMonitorManager::m_pfnMonitor
SOCKET m_sockCommCopy;//与客户端通信的Socket,在关闭服务时才强制关闭此Socket,其余时候不要使用
};
//
class CRemoteHelper
{
//帮助对象,负责完成监控线程对应数据的管理功能,同时提供各种网络读写功能
//请注意:此对象不是线程安全的
public:
CRemoteHelper(CRemoteMonitorManager* pMM,SOCKET sockComm,LPCSTR pszDesc,int iSeq,int iBufferLen=1024*40);
~CRemoteHelper();
const int TMP_BUF_LEN;
public:
//属性获取函数
//得到线程句柄
void SetThreadHandle(HANDLE hThread){m_pHD->SetThreadHandle(hThread );};
//得到连接ID
int GetSeqID(void){return m_pHD->GetSeqID();};
//得到通信用SOCKET,请在外部不要关闭此SOCKET,对象内部会进行处理
SOCKET GetSocket(void){return m_pSock->GetSocket();};
//得到服务对象
CRemoteMonitorManager* GetRemoteMonitorManager(void){return m_pMM;};
//得到数据对象
CRemoteHandlerData* GetRemoteHandlerData(void){return m_pHD;};
//检查服务继续运行标记
BOOL IsGoon(void){return m_pMM->IsGoon();};
public://Send Data
//与客户端之间的数据传递帮助函数
//把信息队列内所有的数据发送到客户端
BOOL SendBufMsgToClient(void);
public://各种帮助功能
// wyy 2003/08/19
//提示客户端输入用户名和密码,在得到输入前会清除缓冲区内所有数据
// fAllowEmptyUser fAllowEmptyPwd 是否允许输入空的用户名和密码
//返回 = 0 成功得到输入
// = 1 时间超时
// = 2 输入不合法
// = 3 网络错误
int GetUsernameAndPwd(CString &szUserName,CString &szPwd,int iTimeout=30,BOOL fAllowEmptyUser=FALSE,BOOL fAllowEmptyPwd=FALSE);
public://buffer manipulate 控制缓冲区的相关功能
// by wenyy 2003/08/18
//得到缓冲区字符指针
const BYTE* GetBuffer(void){return m_pbReadBuf;};
operator const BYTE* (){return m_pbReadBuf;};
//得到缓冲区有效字符长度
int GetBufferDataLen(void){return m_iDataInBuf;};
//清除缓冲区内所有数据
void ClearBuffer(void){m_iDataInBuf=0;};
//从缓冲区中读入一行输入(检测\n or \r 如果多个一起连续出现则会一次性全部清除),同时删除原有数据 (helper function)
//fAllowEmpty 表示是否允许输入空行,如果允许空行则在空行时返回长度为0的字符串
//如果不允许空行,则函数会删除缓冲区最前面的所有回车符号
//pszLine : 缓冲区,iMax : 缓冲区最大长度(必须能够包括NULL字符)
//返回 =0 表示成功,返回数据的长度可以通过strlen(pszLine)得到
//返回 >0 表示提供的缓冲区不够大,同时返回值表示需要的缓冲区的大小,原有数据不改变
//返回 =-1 表示失败,没有发现行结束符号
//返回 =-2 表示失败,缓冲区为空
int RemoveLineFromBuffer(char* pszLine,int iMax,BOOL fAllowEmpty=FALSE);
//从缓冲区中读出指定数量的数据,同时删除原数据,数据会拷贝到pbOut中(pbOut=NULL,表示直接删除数据),iMove指定需要删除的数据长度
//返回 >=0 表示成功,返回剩余数据的长度
//返回 =-1 缓冲区内没有足够数据
int RemoveDataFromBuffer(BYTE* pbOut,int iMove);
//从Socket 中读入数据,函数会检测Socket中是否有数据等待读入,如果有则立即读入,并放入到缓冲区中
//iTimeout 读取时的最大延时,秒
//fEcho 是否将读入的数据回显到客户端
//返回:>0 本次读入的数据,=0 本次未读入数据 =-1 错误发生
//当返回值<0时 iErrorCode = 以下值
// -1 网络错误
// -2 当前缓冲区不足,缓冲区内靠前数据被丢弃
int ReadDataFromClient(int iTimeout,int &iErrorCode,BOOL fEcho=FALSE);
protected:
CTCPSocket* m_pSock;
CRemoteMonitorManager* m_pMM;
CRemoteHandlerData* m_pHD;
BYTE *m_pbReadBuf,*m_pbTempBuf;//用于从网络读入数据
int m_iBufferLen,m_iTempBufferLen;
int m_iDataInBuf;//有效数据的长度
};
/*利用SocketServer与RemoteMonitor实现的带有监控功能服务器
主要功能:
完成服务器所需要的资源分配
提供更简单的帮助类,便于开发者使用
*/
class CSocketServerWithRemoteMonitor
{
public:
CSocketServerWithRemoteMonitor();
~CSocketServerWithRemoteMonitor();
protected:
class COD : public COutputDisplay
{//内部嵌入的显示类,作用用于对实际使用的显示对象进行串行访问
public:
COD(LPCSTR pszSvrName,COutputDisplay* pOutput);
~COD();
//输出
virtual BOOL PutLine(ErrorLevel eLevel,LPCSTR pszOutput);
BOOL printfX(ErrorLevel eLevel,const char *pszFormat,...);
COutputDisplay *m_pOutput;
CSingleAccessLock *m_plockOutput;
};
public://初始化函数,必须全部调用,而且能够全部成功,才可以开始服务
//设置服务器名称
BOOL InitServerName(LPCSTR pszSvrName);
//设置显示类
BOOL InitOutput(COutputDisplay *pOutput);
//设置SOCKET服务器的网络参数
BOOL InitSocketServerNetPara(LPCSTR pszIP,int iListenPort);
//设置监控服务器网络参数
BOOL InitMonitorServerNetPara(LPCSTR pszIP,int iListenPort);
//设置SOCKET服务处理回调函数
BOOL InitSocketServerCallback(PSCHILDPROCESS pSocketClientHandler);
//设置监听服务处理回调函数
BOOL InitMonitorServerCallback(PMONITORHANDLER pRemoteHandler,int iMaxMsgList = 100);
//开始服务
DWORD StartServers(void);
//停止服务
DWORD StopServers(void);
//暂停TCPSocket服务
BOOL PauseTCPSocketServer(void);
//恢复TCPSocket服务
BOOL ResumeTCPSocketServer(void);
public://属性
//得到服务器运行状态
DWORD GetServerState(void){return m_dwServerState;};
enum CServerStatus::ParentThreadStatus GetTCPSocketServerStatus(void){ASSERT(m_pSocketSvrStorage);return m_pSocketSvrStorage->GetServerStatus()->GetParentThreadStatus();};
//得到内部对象指针
CSocketGlobalDataStorage* GetTCPServerStorage(void){return m_pSocketSvrStorage;};
CRemoteMonitorManager* GetRemoteMonitorManager(void){return m_pRemoteSvrManager;};
protected:
//清楚环境并释放内部对象
void ClearEnv(void);
protected:
//服务状态,0=服务器没有运行,1=服务器正在运行 -1=服务器在启动
DWORD m_dwServerState;
//单个服务状态
BOOL m_fTCPServerOK,m_fMonitorServerOK;
//服务对象
COD* m_pInnerOutput;
CSocketGlobalDataStorage *m_pSocketSvrStorage;
CSocketParentThread *m_pSocketSvrThread;
CRemoteMonitorManager *m_pRemoteSvrManager;
PSCHILDPROCESS m_pfunSocketClientHandler;
PMONITORHANDLER m_pfunRemoteHandler;
//相关参数
CString m_szServerName;
CString m_szIp1,m_szIp2; //Socket服务器绑定的本地IP,Monitor服务器绑定的本地IP
int m_iListenPort1,m_iListenPort2;//Socket服务器本地监听端口,Monitor服务器本地监听端口
int m_iMaxMsgList;
};
};
#endif