电脑终端与另一台电脑时间同步

       在网上搜索了很多关于终端时间同步的方案,如通过修改注册表或者通过命令w32tm等方式来指定同步时间,但最终经过测试均有一些瑕疵,通过还是通过C++代码实现之(代码是通过NTP协议实现,以UDP的方式来接收对方的时间)。


客户端代码:

#include
#include  
#pragma comment (lib,"Ws2_32")  


struct   NTP_Packet  
{  
int      Control_Word;     
int      root_delay;     
int      root_dispersion;     
int      reference_identifier;     
__int64 reference_timestamp;     
__int64 originate_timestamp;     
__int64 receive_timestamp;     
int      transmit_timestamp_seconds;     
int      transmit_timestamp_fractions;     
}; 




/************************************************************************/  
/* 函数说明:自动与时间服务器同步更新 
/* 参数说明:无 
/* 返 回 值:成功返回TRUE,失败返回FALSE 
/************************************************************************/  
BOOL UpdateSysTime(char *pTimeServer)  
{  
WORD    wVersionRequested;  
WSADATA wsaData;  


if(!pTimeServer || !pTimeServer[0])
return FALSE;


// 初始化版本  
wVersionRequested = MAKEWORD( 1, 1 );  
if (0!=WSAStartup(wVersionRequested, &wsaData))   
{  
WSACleanup();  
return FALSE;  
}  
if (LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)   
{  
WSACleanup( );  
return FALSE;   
}  


// 这个IP是中国大陆时间同步服务器地址,可自行修改  
SOCKET soc=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);  
struct sockaddr_in addrSrv;  
addrSrv.sin_addr.S_un.S_addr=inet_addr(pTimeServer);  
addrSrv.sin_family=AF_INET;  
addrSrv.sin_port=htons(123);  


NTP_Packet NTP_Send,NTP_Recv;   
NTP_Send.Control_Word   =   htonl(0x0B000000);     
NTP_Send.root_delay     =   0;     
NTP_Send.root_dispersion   =   0;     
NTP_Send.reference_identifier   =   0;     
NTP_Send.reference_timestamp    =   0;     
NTP_Send.originate_timestamp    =   0;     
NTP_Send.receive_timestamp      =   0;     
NTP_Send.transmit_timestamp_seconds     =   0;     
NTP_Send.transmit_timestamp_fractions   =   0;   


if(SOCKET_ERROR==sendto(soc,(const char*)&NTP_Send,sizeof(NTP_Send),  
0,(struct sockaddr*)&addrSrv,sizeof(addrSrv)))  
{  
closesocket(soc);  
return FALSE;  
}  
int sockaddr_Size =sizeof(addrSrv);  
if(SOCKET_ERROR==recvfrom(soc,(char*)&NTP_Recv,sizeof(NTP_Recv),  
0,(struct sockaddr*)&addrSrv,&sockaddr_Size))  
{  
closesocket(soc);  
return FALSE;  
}  
closesocket(soc);  
WSACleanup();  


SYSTEMTIME  newtime;  
float       Splitseconds;  
struct      tm  *lpLocalTime;  
time_t      ntp_time;  


// 获取时间服务器的时间  
ntp_time    = ntohl(NTP_Recv.transmit_timestamp_seconds)-2208988800;  
lpLocalTime = localtime(&ntp_time);  
if(lpLocalTime == NULL)  
{  
return FALSE;  
}  


// 获取新的时间  
newtime.wYear      =lpLocalTime->tm_year+1900;  
newtime.wMonth     =lpLocalTime->tm_mon+1;  
newtime.wDayOfWeek =lpLocalTime->tm_wday;  
newtime.wDay       =lpLocalTime->tm_mday;  
newtime.wHour      =lpLocalTime->tm_hour;  
newtime.wMinute    =lpLocalTime->tm_min;  
newtime.wSecond    =lpLocalTime->tm_sec;  


// 设置时间精度  
Splitseconds=(float)ntohl(NTP_Recv.transmit_timestamp_fractions);  
Splitseconds=(float)0.000000000200 * Splitseconds;  
Splitseconds=(float)1000.0 * Splitseconds;  
newtime.wMilliseconds   =   (unsigned   short)Splitseconds;  


// 修改本机系统时间  
SetLocalTime(&newtime);  
return TRUE;  
}  

// 其中第二个参数表示需要校准的服务器IP地址
int main(int argc, char* argv[])
{
if(argc <= 1)
return 0;


UpdateSysTime(argv[1]);

}


服务端要开启时间校验开关,我写了一个批出来,内容如下:

@echo off

reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32time\TimeProviders\NtpServer" /v "Enabled" /t reg_dword /d "1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32time\Config" /v "AnnounceFlags" /t reg_dword /d "5" /f
net stop w32time && net start w32time


你可能感兴趣的:(winsocket)