获取网络时间同步服务器的时间

时间:5年前   阅读:3913

要获取准确的时间,用于校时或其他操作,可以通过获取时间同步服务器的信息来实现。下面介绍几个常用的时间同步服务器的域名及IP地址:

域名 IP地址

time-a.nist.gov 129.6.15.28

time-b.nist.gov 129.6.15.29

time-a.timefreq.bldrdoc.gov 132.163.4.101

time-b.timefreq.bldrdoc 132.163.4.102

time-c.timefreq.bldrdoc.gov 132.163.4.103

utcnist.colorado.edu 128.138.140.44

time.nist.gov 192.43.244.18

time-nw.nist.gov 131.107.1.10

nist1.datum.com 66.243.43.21

nist1-dc.glassey.com 216.200.93.8

nist1-ny.glassey.com 208.184.49.9

nist1-sj.glassey.com 207.126.98.204

nist1.aol-ca.truetime.com 207.200.81.113

nist1.aol-va.truetime.com 205.188.185.33

国家授时 210.72.145.44

 

 

 

 

 

    可以通过套接字实现对时间的获取,但是获取到的时间信息是 基于1900年1月1日0时0分0秒的信息,也就是说从时间同步服务器返回的是1900年1月1日0时0分0秒至今的秒数。显然需要将其转化为我们常用的时间格式。另外,还需注意一点:时差。

    时间同步服务器返回的时间数据是基于世界时(GMT),也就是格林尼治所在地的标准时间。而北京时间与伦敦GMT存在8小时的时差。所以,在转化过程中要考虑时差。

    下面先介绍利用套接字获取时间数据的函数GetTimeFromServer:

头文件:

#include "winsock2.h"

#pragma comment(lib, "WS2_32.lib") // 显式连接套接字库

函数:

/************************************************************************/

/* 从时间同步服务器获取时间信息 */

/************************************************************************/

DWORD CGetNetworkTimeDlg::GetTimeFromServer(char *ip_addr)

{

// 参数ip_addr:表示指定的时间服务器IP地址

// 返回:自1900年1月1日午0时0分0秒至今的毫秒数 或 0(表示获取失败)

// 默认的时间服务器为"国家授时中心"

if (ip_addr == NULL)

{

ip_addr = _T("210.72.145.44");

}

// 定义WSADATA结构体对象

WSADATA date;

// 定义版本号码

WORD w = MAKEWORD(2, 0);

// 初始化套接字库

if ( ::WSAStartup(w, &date) != 0 )

{

MessageBox(_T("初始化套接字库失败!"));

return 0;

}

// 定义连接套接字句柄

SOCKET s;

// 定义接收信息保存变量

DWORD m_serverTime;

// 创建TCP套接字

s = ::socket(AF_INET, SOCK_STREAM, 0);

if (INVALID_SOCKET == s)

{

MessageBox(_T("创建套接字失败!"));

// 关闭套接字句柄

::closesocket(s);

// 释放套接字库

::WSACleanup();

return 0;

}

// 定义套接字地址结构

sockaddr_in addr;

// 初始化地址结构

addr.sin_family = AF_INET;

addr.sin_port = htons(37);

addr.sin_addr.S_un.S_addr = inet_addr(ip_addr);

// 连接

if ( ::connect(s, (sockaddr*)&addr, sizeof(addr)) !=0 )

{

int errorCode = ::WSAGetLastError();

switch(errorCode)

{

case 10060:

MessageBox(_T("连接超时!"));

break;

case 10051:

MessageBox(_T("网络不可抵达!"));

break;

default:

char temp[20];

sprintf(temp, _T("WSAGetLastError()错误代码:%d"), errorCode);

MessageBox(temp);

}

// 关闭套接字句柄

::closesocket(s);

// 释放套接字库

::WSACleanup();

return 0;

}

// 接收

if ( ::recv(s, (char *)&m_serverTime, 4, MSG_PEEK) <= 0 )

{

MessageBox(_T("接收错误!"));

// 关闭套接字句柄

::closesocket(s);

// 释放套接字库

::WSACleanup();

return 0;

}

// 关闭套接字句柄

::closesocket(s);

// 释放套接字库

::WSACleanup();

// 网络字节顺序转换为主机字节顺序

m_serverTime = ::ntohl(m_serverTime);

// 返回接收到的数据

return m_serverTime;

}

介绍另一个函数,用于将毫秒数(上述函数的返回值)转化为SYSTEMTIME型时间:

/************************************************************************/

/* 将从毫秒数转化为SYSTEMTIME */

/************************************************************************/

SYSTEMTIME CGetNetworkTimeDlg::FormatServerTime(DWORD serverTime)

{

FILETIME ftNew ; 

SYSTEMTIME stNew ; 

stNew.wYear = 1900 ;

stNew.wMonth = 1 ;

stNew.wDay = 1 ;

stNew.wHour = 0 ;

stNew.wMinute = 0 ;

stNew.wSecond = 0 ;

stNew.wMilliseconds = 0 ;

::SystemTimeToFileTime (&stNew, &ftNew);

/* 将SYSTEMTIME结构设定为1900年1月1日午夜(0时)。

并将这个SYSTEMTIME结构传递给SystemTimeToFileTime,将此结构转化为FILETIME结构。

FILETIME实际上只是由两个32位元的DWORD一起组成64位元的整数,

用来表示从1601年1月1日至今间隔为100奈秒(nanosecond)的间隔数。 */ 

LARGE_INTEGER li ; //64位大整数

li = * (LARGE_INTEGER *) &ftNew;

li.QuadPart += (LONGLONG) 10000000 * serverTime; 

ftNew = * (FILETIME *) &li;

::FileTimeToSystemTime (&ftNew, &stNew);

// 返回时间(注意:这里返回的是格林尼治时间,与北京时间相差8小时)

return stNew;

}

说明一点:那就是这样校时存在一定的误差,误差的范围很小,取决于网络延迟,要解决这个问题,可以设置一个计时器,取得网络延迟,加到获得的时间数据后面。

本站声明:网站内容来源于网络,如有侵权,请联系我们https://www.qiquanji.com,我们将及时处理。

微信扫码关注

更新实时通知

上一篇:期权牛市价差策略基础仍在

下一篇:期权权利仓怎么盈利?

网友评论

请先 登录 再评论,若不是会员请先 注册