本程序用于校正本机时间 以下是使用方法 1、默认方式,使用默认时间服务器时间校正本机时间 2、命令行附加一个时间服务器IP参数,将根据指定时间服务器时间校正本机时间,如:
本程序用于校正本机时间
以下是使用方法
1、默认方式,使用默认时间服务器时间校正本机时间
2、命令行附加一个时间服务器IP参数,将根据指定时间服务器时间校正本机时间,如:timecalibration.exe 132.163.4.102
代码:
// timecalibration.cpp : Defines the entry point for the console application.
//
/************************************************************************/
/* */
/************************************************************************/
#include "stdafx.h"
#include <WinSock2.h>
#include <windows.h>
#include <cstdio>
#include <cassert>
#pragma comment(lib,"ws2_32.lib")
class InitSocket
{
public:
InitSocket()
{
WSADATA wsaData={0};
assert(::WSAStartup(MAKEWORD(2,2),&wsaData)==0);
}
~InitSocket()
{
::WSACleanup();
}
};
InitSocket initsocket;
/************************************************************************/
/* timesrv:
132.163.4.101
132.163.4.102
132.163.4.103 */
/************************************************************************/
char szIP[32]="132.163.4.101";
bool SetTime(DWORD tm)
{
FILETIME ft={0};
SYSTEMTIME stTM={0};
stTM.wYear = 1900 ;
stTM.wMonth = 1 ;
stTM.wDay = 1 ;
::SystemTimeToFileTime (&stTM, &ft);
LARGE_INTEGER li ; //64位大整数
li = * (LARGE_INTEGER *) &ft;
li.QuadPart += (LONGLONG) 10000000 * tm;
ft = * (FILETIME *) &li;
::FileTimeToSystemTime (&ft, &stTM);
return ::SetSystemTime (&stTM)==TRUE;
}
BOOL SetConsoleColor(WORD wAttributes)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
return FALSE;
return SetConsoleTextAttribute(hConsole, wAttributes);
}
int main(int argc, char* argv[])
{
assert(SetConsoleColor( FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY));
do
{
if(argc==1)
{
puts("本程序用于校正本机时间");
puts("\r\n");
puts("以下是使用方法");
puts("1、默认方式,使用默认时间服务器时间校正本机时间");
puts("2、命令行附加一个时间服务器IP参数,将根据指定时间服务器时间校正本机时间,\r\n如:timecalibration.exe 132.163.4.102 ");
puts("\r\n按任意键继续...");
getchar();
goto start;
}
else if(argc==2)
{
memcpy(szIP,argv[1],lstrlen(argv[1]));
start:
SOCKADDR_IN addr;
addr.sin_addr.S_un.S_addr=inet_addr(szIP);
if(addr.sin_addr.S_un.S_addr==0xffffffff)
{
puts("非法的IP的地址");
break;
}
addr.sin_family=AF_INET;
addr.sin_port=::htons(IPPORT_TIMESERVER);
SOCKET sClient=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
assert(sClient);
__try
{
DWORD dwset=1;
int ret=::ioctlsocket(sClient,FIONBIO,(LPDWORD)&dwset);
if (ret==SOCKET_ERROR)
{
break;
}
::connect(sClient,(SOCKADDR*)&addr,sizeof addr);
timeval timeout;
fd_set r;
FD_ZERO(&r);
FD_SET(sClient,&r);
timeout.tv_sec=1;
timeout.tv_usec=0;
ret=::select(0,0,&r,0,&timeout);
if (ret<=0) //超时或SOCKET_ERROR
{
puts("连接超时");
break;
}
else
{
puts("连接成功!");
fd_set readset;
FD_ZERO(&readset);
FD_SET(sClient,&readset);
timeout.tv_sec=1;
timeout.tv_usec=0;
ret=::select(0,&readset,0,0,&timeout);
if(ret>0)
{
DWORD tm=0;
int ret=::recv(sClient, (char *) &tm, sizeof tm, 0);
if(ret==sizeof tm)
{
tm=::ntohl(tm);
if (SetTime(tm))
{
puts("校正系统时间成功!");
}
else
puts("设置系统时间失败!");
}
else
puts("接收失败!");
}
else
{
puts("接收超时");
}
}
}
__finally
{
closesocket(sClient);
}
}
}while(0);
puts("\r\n按任意键退出...");
getchar();
return 0;
}
另,根据中国授时中心校准时间(NTP协议):
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <time.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
//---------------------------------------------------------------------------
#pragma argsused
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;
};
BOOL SetTime()
{
WORD wVersionRequested;
WSADATA wsaData;
// 初始化版本
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是中国大陆时间同步服务器地址,可自行修改
// 中国国家授时中心的IP地址是:210.72.145.44
SOCKET soc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("210.72.145.44");
// addrSrv.sin_addr.S_un.S_addr=inet_addr("time-a.timefreq.bldrdoc.gov");
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;
}
int main(int argc, char* argv[])
{
SetTime();
return 0;
}
//---------------------------------------------------------------------------