GrabBag/VrUtils/Src/VrNTPUtils.cpp
2025-06-08 12:48:04 +08:00

216 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}