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