216 lines
4.3 KiB
C++
216 lines
4.3 KiB
C++
#include "VrNTPUtils.h"
|
||
|
||
#ifdef _WIN32
|
||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||
#define _CRT_SECURE_NO_WARNINGS
|
||
#include <WS2tcpip.h>
|
||
#include <WinSock2.h>
|
||
#pragma comment(lib,"Ws2_32.lib")
|
||
#else
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <sys/types.h>
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/ioctl.h>
|
||
#include <unistd.h>
|
||
#include <arpa/inet.h>
|
||
|
||
#define SOCKET int
|
||
#define INVALID_SOCKET -1
|
||
#define SOCKET_ERROR -1
|
||
#endif
|
||
#include <time.h>
|
||
|
||
struct NTP_Packet
|
||
{
|
||
int Control_Word;
|
||
int root_delay;
|
||
int root_dispersion;
|
||
int reference_identifier;
|
||
long long reference_timestamp;
|
||
long long originate_timestamp;
|
||
long long receive_timestamp;
|
||
int transmit_timestamp_seconds;
|
||
int transmit_timestamp_fractions;
|
||
};
|
||
|
||
CrNTPUtils::CrNTPUtils()
|
||
: m_bValidIP(false)
|
||
, m_nPort(123)
|
||
{
|
||
}
|
||
|
||
CrNTPUtils::~CrNTPUtils()
|
||
{
|
||
}
|
||
|
||
|
||
/// 初始化NTPClient
|
||
bool CrNTPUtils::InitNTPClient(char* sIP, int nPort)
|
||
{
|
||
bool bRet = true;
|
||
|
||
#ifdef _WIN32
|
||
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;
|
||
}
|
||
#endif
|
||
if (nullptr != sIP)
|
||
{
|
||
m_bValidIP = true;
|
||
#ifdef _WIN32
|
||
strcpy_s(m_sIP, sIP);
|
||
#else
|
||
strcpy(m_sIP, sIP);
|
||
#endif // _WIN32
|
||
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
/// 退出NTPClient
|
||
bool CrNTPUtils::ExitNTPClient()
|
||
{
|
||
bool bRet = true;
|
||
|
||
|
||
return bRet;
|
||
}
|
||
|
||
///获取时间
|
||
bool CrNTPUtils::GetSystemTime(SYSTEMTIME& newtime)
|
||
{
|
||
// 这个IP是中国大陆时间同步服务器地址,可自行修改
|
||
SOCKET soc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
struct sockaddr_in addrSrv;
|
||
|
||
// time.ustc.edu.cn 202.38.64.7
|
||
// ntp.aliyun.com 203.107.6.88
|
||
#ifdef _WIN32
|
||
if (!m_bValidIP)
|
||
{
|
||
inet_pton(AF_INET, "203.107.6.88", &addrSrv);//time.ustc.edu.cn");
|
||
}
|
||
else
|
||
{
|
||
inet_pton(AF_INET, m_sIP, &addrSrv);
|
||
}
|
||
#else
|
||
if (!m_bValidIP)
|
||
{
|
||
addrSrv.sin_addr.s_addr = inet_addr("203.107.6.88");//time.ustc.edu.cn");
|
||
}
|
||
else
|
||
{
|
||
addrSrv.sin_addr.s_addr = inet_addr(m_sIP);
|
||
}
|
||
#endif // _WIN32
|
||
|
||
|
||
addrSrv.sin_family = AF_INET;
|
||
addrSrv.sin_port = htons(m_nPort);
|
||
|
||
NTP_Packet NTP_Send, NTP_Recv;
|
||
NTP_Send.Control_Word = htonl(0x1B000000);
|
||
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)))
|
||
{
|
||
#ifdef _WIN32
|
||
closesocket(soc);
|
||
#else
|
||
close(soc);
|
||
#endif // _WIN32
|
||
|
||
return false;
|
||
}
|
||
socklen_t sockaddr_Size = sizeof(addrSrv);
|
||
if (SOCKET_ERROR == recvfrom(soc, (char*)&NTP_Recv, sizeof(NTP_Recv), 0, (struct sockaddr*)&addrSrv, &sockaddr_Size))
|
||
{
|
||
#ifdef _WIN32
|
||
closesocket(soc);
|
||
#else
|
||
close(soc);
|
||
#endif // _WIN32
|
||
return false;
|
||
}
|
||
#ifdef _WIN32
|
||
closesocket(soc);
|
||
WSACleanup();
|
||
#else
|
||
close(soc);
|
||
#endif
|
||
|
||
float Splitseconds;
|
||
struct tm* lpLocalTime = nullptr;
|
||
time_t ntp_time;
|
||
|
||
// 获取时间服务器的时间
|
||
ntp_time = ntohl(NTP_Recv.transmit_timestamp_seconds) - 2208988800;
|
||
#ifdef _WIN32
|
||
localtime_s(lpLocalTime , &ntp_time);
|
||
#else
|
||
lpLocalTime = localtime(&ntp_time);
|
||
#endif
|
||
|
||
if (lpLocalTime == nullptr)
|
||
{
|
||
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;
|
||
return true;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* 函数说明:自动与时间服务器同步更新
|
||
/* 参数说明:无
|
||
/* 返 回 值:成功返回TRUE,失败返回FALSE
|
||
/************************************************************************/
|
||
bool CrNTPUtils::_UpdateDate()
|
||
{
|
||
SYSTEMTIME newtime;
|
||
bool bRet = GetSystemTime(newtime);
|
||
// 修改本机系统时间
|
||
#ifdef _WIN32
|
||
SetLocalTime(&newtime);
|
||
#endif
|
||
return true;
|
||
} |