VC实现内网时间同步+进程守护

**

VC实现内网时间同步+进程守护

**

问题的由来
单位上现有服务器实体机+虚拟机共200+,一直存在时间准确性和一致性方面的问题。期间用过不少时间同步工具,例如atomic time synchronizer-原子时钟同步器、XiaoMoTimeSync等,但都不太理想。加上服务器需要保证业务进程和服务连续不断地工作,也找不到合适的监控管理软件,无奈之下,最后自己亲手操刀写了一个。
服务器的时间问题
服务器(以Window服务器为例)的时间来源大致有以下几种:1、主板晶振(时间不准);2、Window自带的对时功能(通常连不上时间服务器);3、应用程序校时(例如以数据库服务器的时间为准);4、虚拟化平台提供时间源(例如vCenter、ESXI主机);5、使用第三方对时软件。
上述前两种方法明显不靠谱,第三、第四种方法的时间源仍然是个问题,最终还是需要我们自己搭建一个内网的NTP服务器,这个服务器通过访问外网的NTP服务器(例如cn.pool.ntp.org、ntp1.aliyun.com)校准自己的时间,同时对内网提供NTP授时服务。
网络对时的实现方法
编程环境:Win7旗舰版(x64)+VC2005
不用很新的版本,用VC2005编写+静态编译,完成后程序只有400K,操作系统只需要安装有VC2005的运行库就能正常运行,不需要额外安装DotNet。
对时方法1:Socket 编程
具体代码,参考了网上的资料:
vc++6.0 同步本机时间到Internet NTP服务器 编译通过
https://blog.csdn.net/jiftlixu/article/details/6013837?locationNum=3
对时方法2:注册表编程
网上这方面的资料比较多,需要修改的注册表键基本上都在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\下(服务端和客户端不一样),还有一个在HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\DATETIME\SERVERS\。
重启w32time服务和开启防火墙UDP123端口,可以用批处理实现。例如:

CString  strCmd = "/c sc start w32time";
ShellExecute(NULL, "open", "cmd.exe", strCmd, NULL, SW_HIDE);
strCmd = "/c netsh firewall set portopening udp 123 NTPSERVER enable";
ShellExecute(NULL, "open", "cmd.exe", strCmd, NULL, SW_HIDE);

程序本身做NTP服务器也是通过修改注册表来实现。
关于服务器的进程和服务
服务器需要保证业务连续,不能随意中断。当服务器开机时,业务进程和服务需要自动运行。开机后,当业务进程和服务出现异常时(进程异常退出、服务异常停止等),需要及时发现并重新启动进程或者拉起服务。
要实现上述目的,只要将需要守护的进程和监控的服务写到配置文件(ini文件、xml文件等),然后定时轮询即可。

//监控配置文件,包含两个Section:[Service]和[Process]
CString monFile = "C:\\Daemon.cfg";  
rowNum GetRows()  //获得需要监控的服务和进程的数量
{   //rowNum是自己定义的结构体
	trowNum retNum;
	CStdioFile file;
	CString str;
	int i=0,j=0,k=0;
	if(file.Open(monFile,CFile::modeRead))
	{
		while(file.ReadString(str))
		{
			i++;
			if(str == "[Service]") j = i; //前面有注释语句
			if(str == "[Process]") k = i;
		}
		file.Close();
		int row1 = k - j -1;  //监控服务的数量
		int row2 = i - k;      //监控进程的数量
		retNum.num1 = row1;
		retNum.num2 = row2;
	}
	else
	{
		int row1 = 0;  //监控服务的数量
		int row2 = 0;  //监控进程的数量
		retNum.num1 = row1;
		retNum.num2 = row2;
	}
	return retNum;
}

进程守护的实现方法
1、判断指定进程是否存在

BOOL IsOpen(CString strFind)  //判断进程是否存在
{
	PROCESSENTRY32 pe32;
	pe32.dwSize = sizeof(pe32);
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	if( hProcessSnap == INVALID_HANDLE_VALUE ) return FALSE;

	BOOL bMore = Process32First( hProcessSnap,&pe32 );
	while(bMore)
	{
		bMore = Process32Next( hProcessSnap,&pe32 );
		CString strExeFile;
		strExeFile.Format("%s",pe32.szExeFile);
		if( strExeFile.CompareNoCase(strFind) == 0 )
		{
			CloseHandle( hProcessSnap );
			return TRUE;
		}
	}
	CloseHandle( hProcessSnap );
	return FALSE;
}
2、启动进程:
nRet = WinExec(strPath,SW_SHOWNORMAL);

服务监控的实现方法
1、获取指定服务的状态

CString GetStatus(CString pServiceName)
{   
	SC_HANDLE hSC = ::OpenSCManager( NULL,NULL, GENERIC_EXECUTE);
	if( hSC == NULL)
	{
		//return SEV_ERROR; //无法连接服务管理器
		return "无法连接服务管理器";
	}
	// 打开服务。
	SC_HANDLE hSvc = ::OpenService( hSC, pServiceName, SERVICE_START | SERVICE_QUERY_STATUS | SERVICE_STOP);
	if( hSvc == NULL)
	{
		::CloseServiceHandle( hSC);
		//return SEV_NO;  //无法打开服务
		return "无法打开服务"; 
	}
	// 获得服务的状态
	SERVICE_STATUS status;
	CString strRet;
	if( ::QueryServiceStatus( hSvc, &status) == FALSE)
	{   
		// TRACE( "Get Service state error。");
		::CloseServiceHandle( hSvc);
		::CloseServiceHandle( hSC);
		return "获取服务状态失败"; 
	}   
	else
	{   
		::CloseServiceHandle( hSvc);
		::CloseServiceHandle( hSC);
		DWORD dwValue = status.dwCurrentState; 
		switch(dwValue)
		{
		case SERVICE_CONTINUE_PENDING:
			strRet="恢复挂起";
			break;
		case SERVICE_PAUSE_PENDING:
			strRet="暂停挂起";
			break;
		case SERVICE_PAUSED:
			strRet="服务暂停";
			break;
		case SERVICE_RUNNING:
			strRet="正在运行";
			break;
		case SERVICE_START_PENDING:
			strRet="正在启动";
			break;
		case SERVICE_STOP_PENDING:
			strRet="正在停止";
			break;
		case SERVICE_STOPPED:
			strRet="服务停止";
			break;
		default:
			strRet="未知状态";
			break;
		}
		return strRet;
	}   
}

2、启动服务
方法同上,用ShellExecute函数。
程序开机自启的实现
同样是通过写注册表来实现,这里是先把自身复制到Windows目录后,再写注册表。注册表路径:“Software\Microsoft\Windows\CurrentVersion\Run”。
另外,我在程序里加入了注册激活的功能,没注册的使用功能会受限制。
程序界面如下: 在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值