// SyncTimeTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include "DateTime.h"
FILE* g_logfile = stdout;
const char* szTimeServer[] =
{
"time-a.timefreq.bldrdoc.gov",
"time-b.timefreq.bldrdoc.gov",
"time-c.timefreq.bldrdoc.gov",
"utcnist.colorado.edu",
"time-nw.nist.gov",
"nist1.nyc.certifiedtime.com",
"nist1.dc.certifiedtime.com",
"nist1.sjc.certifiedtime.com",
"nist1.datum.com",
"ntp2.cmc.ec.gc.ca",
"ntps1-0.uni-erlangen.de",
"ntps1-1.uni-erlangen.de",
"ntps1-2.uni-erlangen.de",
"ntps1-0.cs.tu-berlin.de",
"time.ien.it",
"ptbtime1.ptb.de",
"ptbtime2.ptb.de"
};
//由主机名获得IP地址列表
int getsockaddrbyname(const char* name, struct in_addr* addrlist, int maxcount, int* preturncount)
{
int count = 0;
struct hostent* host = gethostbyname(name);
if(host)
{
char **pptr;
// fprintf(g_logfile, "official hostname:%s\n",host->h_name);
// for(pptr = host->h_aliases; *pptr != NULL; pptr++)
// fprintf(g_logfile, " alias:%s\n",*pptr);
switch(host->h_addrtype)
{
case AF_INET:
case AF_INET6:
for(pptr = host->h_addr_list; *pptr != NULL; pptr++)
{
memcpy(&addrlist[count++], *pptr, sizeof(struct in_addr));
struct in_addr *inaddr = (struct in_addr *)(*pptr);
// fprintf(g_logfile, " address:%s\n", inet_ntoa(*inaddr));
}
break;
default:
// fprintf(g_logfile, "unknown address type\n");
break;
}
if(preturncount) *preturncount = count;
}
return count;
}
//获得时间服务器的时间
int getinternettime(const char* server, int port = 37, int timeout = 1000)
{
int ret = 0;
DateTime tmDate;
long days_of_1900 = 0;
int addr_count = 0;
struct in_addr addr_list[32] = {0};
fprintf(g_logfile, "[%s] \n", server);
LoadDateStruct(&tmDate, 1900, 1, 1);
days_of_1900 = DateToDayNumber(&tmDate); //自1900年以来的天数
if(getsockaddrbyname(server, addr_list, 32, &addr_count))
{
for(int i = 0; i < addr_count; i++)
{
struct sockaddr_in clientaddr;
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr = addr_list[i];
clientaddr.sin_port = htons(port);
SOCKET hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET != hsock)
{
setsockopt(hsock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
fprintf(g_logfile, "connect...\n");
DWORD start = GetTickCount();
if(connect(hsock, (struct sockaddr*)&clientaddr, sizeof(clientaddr)) == 0)
{
int recv_bytes = 0;
DWORD dwTime = 0; //用来存放服务器传来的标准时间数据
unsigned char nTime[8] = {0}; //临时接收数据
fprintf(g_logfile, "recv...\n");
if((recv_bytes = recv(hsock, (char*)nTime, sizeof(nTime), 0)) > 0)
{
dwTime = (nTime[0] << 24) | (nTime[1] << 16) | (nTime[2] << 8) | nTime[3]; //整合数据
if(dwTime > 0)
{
dwTime += 8 * ONEHOUROFSECOND; //UTC时间转换成北京时间, 加8小时
//服务器传来的数据是自从1900年以来的秒数
int second = (dwTime % 60);
int minute = (dwTime / 60) % 60;
int hour = (dwTime / ONEHOUROFSECOND) % 24;
int days = (dwTime / ONEDAYOFSECONDS);
DayNumberToDate(days_of_1900 + days, &tmDate);
fprintf(g_logfile, "%04d-%02d-%02d %02d:%02d:%02d",
tmDate.wYear, tmDate.wMonth, tmDate.wDay, hour, minute, second);
fprintf(g_logfile, "\t0x%X-0x%X-0x%X-0x%X", nTime[0], nTime[1], nTime[2], nTime[3]);
if(tmDate.wYear != 2013 || tmDate.wMonth != 1 || tmDate.wDay != 7)
{
int k = 0;
}
ret = 1;
}
}
else
fprintf(g_logfile, "recv bytes %d, error %d", recv_bytes, WSAGetLastError());
}
else
fprintf(g_logfile, "connect error %d, timeout %dms", WSAGetLastError(), GetTickCount() - start);
closesocket(hsock);
}
}
}
else
fprintf(g_logfile, "gethostbyname error %d", WSAGetLastError());
return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsd = {0};
WSAStartup(MAKEWORD(2, 2), &wsd);
g_logfile = fopen("\\ResidentFlash\\netclock_log.txt", "at");
if(g_logfile == NULL)
g_logfile = stdout;
while(1)
{
fprintf(g_logfile, "-----------------------------------------------------------\n");
int count = sizeof(szTimeServer) / sizeof(szTimeServer[0]);
for(int i = 0; i < count; i++)
{
if(getinternettime(szTimeServer[i]))
fprintf(g_logfile, " \t OK\n");
else
fprintf(g_logfile, " \t FAIL\n");
fprintf(g_logfile, "\n");
}
}
if(g_logfile && g_logfile != stdout)
fclose(g_logfile);
WSACleanup();
return 0;
}