SNTP 获取时间服务器UTC时间
来源:互联网 发布:淘宝直播间入口 编辑:程序博客网 时间:2024/05/17 02:23
// SntpTest.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <math.h>#include <time.h>#include <winsock2.h>#pragma comment(lib, "wsock32.lib")//ref : www.ietf.org/rfc/rfc2030.txt/* 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|LI | VN |Mode | Stratum | Poll | Precision |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Root Delay |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Root Dispersion |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Reference Identifier |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Reference Timestamp (64) || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Originate Timestamp (64) || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Receive Timestamp (64) || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || Transmit Timestamp (64) || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Key Identifier (optional) (32) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| || || Message Digest (optional) (128) || || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/#pragma pack(push, 1)typedef struct _tagNTPTimestamp_t{ unsigned char Seconds[4]; //(32-bit unsigned fixed-point number. Big-endian) unsigned char Seconds_Fraction[4]; //((32-bit unsigned fixed-point number. Big-endian) }NTPTIMESTAMP, *LPNTPTIMESTAMP;typedef struct _tagNTPMsgFmtV4_t{ struct { unsigned char LI:2; //Leap Indicator //0 no warning //1 last minute has 61 seconds //2 last minute has 59 seconds) //3 alarm condition (clock not synchronized) unsigned char VN:3; //Version Number //3 for Version 3 (IPv4 only) //4 for Version 4 (IPv4, IPv6 and OSI) unsigned char Mode:3; //indicating the mode //0 reserved //1 symmetric active //2 symmetric passive //3 client //4 server //5 broadcast //6 reserved for NTP control message //7 reserved for private use unsigned char Stratum; //stratum level of the local clock //0 unspecified or unavailable //1 primary reference (e.g., radio clock) //2-15 secondary reference (via NTP or SNTP) //16-255 reserved unsigned char Poll; //Poll Interval unsigned char Precision; //Precision }; unsigned char Root_Delay[4]; //Root Delay (32-bit signed fixed-point number. Big-endian) unsigned char Root_Dispersion[4]; //Root Dispersion (32-bit unsigned fixed-point number. Big-endian) char Reference_Identifier[4]; //Reference Identifier //LOCL uncalibrated local clock used as a primary reference for a subnet without external means of synchronization //PPS atomic clock or other pulse-per-second source individually calibrated to national standards //ACTS NIST dialup modem service //USNO USNO modem service //PTB PTB (Germany) modem service //TDF Allouis (France) Radio 164 kHz //DCF Mainflingen (Germany) Radio 77.5 kHz //MSF Rugby (UK) Radio 60 kHz //WWV Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz //WWVB Boulder (US) Radio 60 kHz //WWVH Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz //CHU Ottawa (Canada) Radio 3330, 7335, 14670 kHz //LORC LORAN-C radionavigation system //OMEG OMEGA radionavigation system //GPS Global Positioning Service //GOES Geostationary Orbit Environment Satellite NTPTIMESTAMP Reference_Timestamp; //Reference Timestamp (64-bit timestamp format. Big-endian) NTPTIMESTAMP Originate_Timestamp; //Originate Timestamp (64-bit timestamp format. Big-endian) NTPTIMESTAMP Receive_Timestamp; //ReceiveTimestamp (64-bit timestamp format. Big-endian) NTPTIMESTAMP Transmit_Timestamp; //Transmit Timestamp (64-bit timestamp format. Big-endian) //char Key_Identifier[4]; //Key Identifier (optional) //unsigned char Message_Digest[16]; //Message Digest (optional) }NTPMSGFMTV4, *LPNTPMSGFMTV4;#pragma pack(pop)//convert NTP timer to system timeBOOL _SNTPTimeToSystemTime(LPNTPTIMESTAMP pNTPTimeStame, SYSTEMTIME &tmDest){ // Verifies will fail if the needed buffer size is too large#define _MIN_DATE (-657434L) // about year 100#define _MAX_DATE 2958465L // about year 9999 // Half a second, expressed in days#define _HALF_SECOND (1.0/172800.0) double dtSrc = 0; double fMillsecods = 0; //convert NTP time to days unit { u_long uSeconds = ntohl( *((u_long*)&pNTPTimeStame->Seconds[0]) ); //seconds u_long uSecondsF = ntohl( *((u_long*)&pNTPTimeStame->Seconds_Fraction[0]) ); //Seconds Fraction //convert Seconds Fraction to double type double fSecondF = 0; { u_long uSecondF =uSecondsF; int iLen = 0; double fPart[64] = {0}; while(uSecondF && iLen < 64-1) { fPart[iLen++] = (uSecondF % 10); uSecondF = uSecondF/10; } double fDiv = 10.0; while((--iLen) >= 0) { fSecondF += fPart[iLen]/fDiv; fDiv *= 10; } } double vtDate = uSeconds; if( pNTPTimeStame->Seconds[0] & 0x80 ) //since from 1900,January,1,00:00:00 to 2036 { } else //since form 6h 28m 16s UTC on 7 February 2036 { vtDate += 0xFFFFFFFFU; //overflow } vtDate += (2 * 24 * 3600); //system time Dec. 30, 1899 to NTP Jan.1, 1900 dtSrc = vtDate / (24 * 60 * 60); //convert to days fMillsecods = (int)(fSecondF * 1000.0); } if (dtSrc > _MAX_DATE || dtSrc < _MIN_DATE) // about year 100 to about 9999return FALSE; // The legal range does not actually span year 0 to 9999. long nDays; // Number of days since Dec. 30, 1899 long nDaysAbsolute; // Number of days since 1/1/0 long nSecsInDay; // Time in seconds since midnight long nMinutesInDay; // Minutes in day long n400Years; // Number of 400 year increments since 1/1/0 long n400Century; // Century within 400 year block (0,1,2 or 3) long n4Years; // Number of 4 year increments since 1/1/0 long n4Day; // Day within 4 year block // (0 is 1/1/yr1, 1460 is 12/31/yr4) long n4Yr; // Year within 4 year block (0,1,2 or 3) BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year double dblDate = dtSrc; // tempory serial date // If a valid date, then this conversion should not overflow nDays = (long)dblDate; // Round to the second dblDate += ((dtSrc > 0.0) ? _HALF_SECOND : -_HALF_SECOND); nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899 dblDate = fabs(dblDate); nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.); // Calculate the day of week (sun=0, mon=1...) tmDest.wDayOfWeek = (int)((nDaysAbsolute - 1) % 7L) + 0; // Leap years every 4 yrs except centuries not multiples of 400. n400Years = (long)(nDaysAbsolute / 146097L); // Set nDaysAbsolute to day within 400-year block nDaysAbsolute %= 146097L; // -1 because first century has extra day n400Century = (long)((nDaysAbsolute - 1) / 36524L); // Non-leap century if (n400Century != 0) { // Set nDaysAbsolute to day within century nDaysAbsolute = (nDaysAbsolute - 1) % 36524L; // +1 because 1st 4 year increment has 1460 days n4Years = (long)((nDaysAbsolute + 1) / 1461L); if (n4Years != 0) { n4Day = (long)((nDaysAbsolute + 1) % 1461L); } else { bLeap4 = FALSE; n4Day = (long)nDaysAbsolute; } } else { // Leap century - not special case! n4Years = (long)(nDaysAbsolute / 1461L); n4Day = (long)(nDaysAbsolute % 1461L); } if (bLeap4) { // -1 because first year has 366 days n4Yr = (n4Day - 1) / 365; if (n4Yr != 0) n4Day = (n4Day - 1) % 365; } else { n4Yr = n4Day / 365; n4Day %= 365; } // n4Day is now 0-based day of year. Save 1-based day of year, year number int tm_yday = (int)n4Day + 1; /* days since January 1 - [0,365] */ tmDest.wYear = (WORD)(n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr); do { // Handle leap year: before, on, and after Feb. 29. if (n4Yr == 0 && bLeap4) { // Leap Year if (n4Day == 59) { /* Feb. 29 */ tmDest.wMonth = 2; tmDest.wDay = 29; break; //goto DoTime; } // Pretend it's not a leap year for month/day comp. if (n4Day >= 60) --n4Day; } // Make n4DaY a 1-based day of non-leap year and compute // month/day for everything but Feb. 29. ++n4Day; // Month number always >= n/32, so save some loop time */ // One-based array of days in year at month start static int _MonthDays[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; for (tmDest.wMonth = (n4Day >> 5) + 1; n4Day > _MonthDays[tmDest.wMonth]; tmDest.wMonth++); tmDest.wDay = (int)(n4Day - _MonthDays[tmDest.wMonth-1]); }while(0);//DoTime: if (nSecsInDay == 0) { tmDest.wHour = tmDest.wMinute = tmDest.wSecond = 0; } else { tmDest.wSecond = (WORD)(nSecsInDay % 60L); nMinutesInDay = nSecsInDay / 60L; tmDest.wMinute = (WORD)(nMinutesInDay % 60); tmDest.wHour = (WORD)(nMinutesInDay / 60); } tmDest.wMilliseconds = (WORD)fMillsecods; return TRUE;}int _SNTPGetUTCTime(const char *szSntpServer, SYSTEMTIME *ptmSys){ BOOL bRet = 0; do { //init socket int err = 0; WSADATA wsa; err = WSAStartup(MAKEWORD(2, 0), &wsa); if(err != 0) { bRet = -1; break; } SOCKET sSession = INVALID_SOCKET; do { //get host ip by name hostent * hp = gethostbyname(szSntpServer); if(hp == NULL) { bRet = -2; break; } sockaddr_in SvrIp; SvrIp.sin_family= AF_INET; memcpy(&SvrIp.sin_addr, hp->h_addr, sizeof(SvrIp.sin_addr)); SvrIp.sin_port= htons(123); //create socket sSession = socket(AF_INET, SOCK_DGRAM, 0); if(sSession == INVALID_SOCKET) { bRet = -3; break; } int iSizeSocketIn = sizeof(SOCKADDR_IN); //sendto int nTime = 3000; setsockopt(sSession, SOL_SOCKET, SO_SNDTIMEO, (char *)&nTime, sizeof(nTime)); NTPMSGFMTV4 txMsg; memset(&txMsg, 0, sizeof(txMsg)); txMsg.LI = 3; //alarm condition (clock not synchronized) txMsg.VN = 4; //4 for Version 4 (IPv4, IPv6 and OSI) txMsg.Mode = 4; //4 server if(SOCKET_ERROR == sendto(sSession, (const char*)&txMsg, sizeof(txMsg), 0, (sockaddr*)&SvrIp, iSizeSocketIn)) { bRet = -4; break; } //recvfrom setsockopt(sSession, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTime, sizeof(nTime)); NTPMSGFMTV4 rxMsg; memset(&rxMsg, 0, sizeof(rxMsg)); int nLenRcv = recvfrom(sSession, (char *)&rxMsg, sizeof(rxMsg), 0, (sockaddr*)&SvrIp, &iSizeSocketIn); if(nLenRcv == SOCKET_ERROR) { bRet = -5; break; } //use convert SNTP date to system time SYSTEMTIME tmSys; if(!_SNTPTimeToSystemTime(&rxMsg.Transmit_Timestamp, tmSys)) { bRet = -6; break; } if(ptmSys) { *ptmSys = tmSys; } bRet = 1; }while(0); //close socket if(sSession != INVALID_SOCKET) { closesocket(sSession); sSession = INVALID_SOCKET; } //WASClearup WSACleanup(); }while(0); return bRet;}int TestSNTP(){ LPCTSTR szTimeSvr[]= { "time.windows.com", "time.nist.gov", "time-nw.nist.gov", "pool.ntp.org", "europe.pool.ntp.org", "asia.pool.ntp.org", "oceania.pool.ntp.org", "north-america.pool.ntp.org", "south-america.pool.ntp.org", "africa.pool.ntp.org", "ca.pool.ntp.org", "uk.pool.ntp.org", "us.pool.ntp.org", "au.pool.ntp.org", 0 }; for(size_t i = 0; szTimeSvr[i] ; ++i) { SYSTEMTIME tm = {0}; if(_SNTPGetUTCTime(szTimeSvr[i], &tm) > 0) { printf("%s: %04dY-%02dM-%02dD (Week %d) %02dH:%02dM:%02dS.%03dms\n", szTimeSvr[i], tm.wYear, tm.wMonth, tm.wDay, tm.wDayOfWeek, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds); } } return 0;}int main(int argc, char* argv[]){ TestSNTP(); printf("Hello World!\n"); return 0;}
/* debug outputtime.windows.com: 2015Y-05M-25D (Week 1) 07H:05M:20S.915mstime.nist.gov: 2015Y-05M-25D (Week 1) 07H:05M:20S.133mspool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:24S.573msoceania.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:31S.116mssouth-america.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:35S.617msafrica.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:35S.235msca.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:35S.405msuk.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:36S.580msus.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:36S.185msau.pool.ntp.org: 2015Y-05M-25D (Week 1) 07H:05M:36S.328msHello World!Press any key to continue*/
0 0
- SNTP 获取时间服务器UTC时间
- C#的SNTP客户端取SNTP时间服务器代码
- Java获取UTC时间
- Java 获取UTC时间
- 获取本地时间,UTC时间
- 【ESP8266】使用SNTP接口获取时间
- 【shell命令】获取utc时间
- -UTC时间及时区获取
- java 获取UTC时间格式
- Android SNTP 时间同步
- 获取本地时间与UTC时间
- UTC时间
- utc时间
- Android获取UTC时间的方式
- C++ 获取UTC时间精确到微妙
- 获取13/10位UTC格式时间
- UTC时间&本地时间
- NTP/SNTP时间同步参考
- java实现 SSL双向认证
- 大家嘴上所说的互联网+
- Appium TestNg Maven Android Eclipse java简单启动实例
- hdu4825---Xor Sum(Trie + 贪心)
- 第十二周 项目2-摩托车继承自行车和机动车
- SNTP 获取时间服务器UTC时间
- 余弦距离、欧氏距离和杰卡德相似性度量的对比分析
- UIWebView与动态创建Cell
- IOS-TextField知多少
- WSAAccept与WSAAccept的ConditionAcceptFunction
- JSON.parse和eval的区别
- UICollectionViewLayout
- top命令
- 数据挖掘10大算法(1)——PageRank