#include "VrNTPUtils.h" #ifdef _WIN32 #define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include #include #pragma comment(lib,"Ws2_32.lib") #else #include #include #include #include #include #include #include #include #include #include #define SOCKET int #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #endif #include 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; }