名将家书:怎样设置服务器与客户端时间同步
来源:百度文库 编辑:中财网 时间:2024/05/09 02:59:47
一 域环境,默认情况下,所有计算机都会和域控制器同步时间的,无需特别设置。
二 工作组环境
1)如果所有机器都可以访问internet,可以直接使用time.windows.com(默认的配置)
2)如果机器不能访问internet,或者有防火墙导致无法同步,可以在2003服务器上创建时间服务器,客户端XP系统设置时间服务器地址为2003服务器。
三 客户端设置
双击托盘区显示时间的地方,出现对话框之后选择Internet时间设置时间服务器的地址。默认为time.windows.com,设置为2003服务器地址,然后单击“立即更新”按钮实现“时间同步”。
四 服务器端设置
1. 单击“开始”,单击“运行”,键入 regedit,然后单击“确定”。
2. 找到并单击下面的注册表子项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config\AnnounceFlags
3. 在右窗格中,右键单击“AnnounceFlags”,然后单击“修改”。
4. 在“编辑 DWORD 值”的“数值数据”框中键入 A,然后单击“确定”。
5. 退出注册表编辑器。
6. 在命令提示符处,键入以下命令以重新启动 Windows 时间服务,然后按 Enter:
net stop w32time && net start w32time
最近因工作原因,需要客户端计算机与FTP服务器时间上进行同步,上网搜集了些时间同步的方法记录下来, 以备不需之用!1.时间协议(TIME protocol)
时间协议(TIME protocol)是一个在RFC 868内定义的网络协议。它用作提供机器可读的日期时间资讯。
时间协议可以在TCP或UDP上使用。在TCP上,主机会连接支援时间协议的服务器的TCP埠 37。服务器会传送32位二进制数字然后断开连接,数字表示由格林威治时间1900年1月1日午夜0时0分0秒至当时的总秒数。主机在接收到时间后断开连接。
在UDP上,客户端会每送一个(通常为空的)数据包到UDP埠 37。服务器会把包含时间的数据包传回。在过程中没有进行连线。
现时,时间协议已经被网络时间协议(Network Time Protocol,NTP)所取代。
使用时间协议需要在服务器端开启时间服务,目前在windows中我还没找到系统自带的开启时间服务的方法, 但网络上有些小软件可以帮助实现(如NetTime网络时标, 它支持Time,NTP等好几种协议, 可惜需要注册使用).
基于时间协议客户端实现代码:view plaincopy to clipboardprint?
01.void SetLocalSystemTime(u_long ulTime)
02.{
03. FILETIME ftNew ;
04. SYSTEMTIME stOld, stNew ;
05. ::GetLocalTime (&stOld) ; //首先取得目前的本地时间
06. stNew.wYear = 1900 ;
07. stNew.wMonth = 1 ;
08. stNew.wDay = 1 ;
09. stNew.wHour = 0 ;
10. stNew.wMinute = 0 ;
11. stNew.wSecond = 0 ;
12. stNew.wMilliseconds = 0 ;
13. ::SystemTimeToFileTime (&stNew, &ftNew);
14. /* 将SYSTEMTIME结构设定为1900年1月1日午夜(0时)。
15. 并将这个SYSTEMTIME结构传递给SystemTimeToFileTime,将此结构转化为FILETIME结构。
16. FILETIME实际上只是由两个32位元的DWORD一起组成64位元的整数,
17. 用来表示从1601年1月1日至今间隔为100奈秒(nanosecond)的间隔数。 */
18. LARGE_INTEGER li ; //64位大整数
19. li = * (LARGE_INTEGER *) &ftNew;
20. li.QuadPart += (LONGLONG) 10000000 * ulTime;
21. ftNew = * (FILETIME *) &li;
22. ::FileTimeToSystemTime (&ftNew, &stNew);
23. ::SetSystemTime (&stNew);
24.}
25.bool SetSystemFromSocket(LPCSTR lpRemote)
26.{
27. bool ret = true;
28. WSADATA WSAData;
29. ::WSAStartup (MAKEWORD(2,2), &WSAData);
30. SOCKET skt=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
31. TCHAR msg[512];
32. if (skt == INVALID_SOCKET)
33. {
34. goto END;
35. }
36. struct sockaddr_in sa ;
37. sa.sin_family = AF_INET ;
38. sa.sin_port = ::htons (IPPORT_TIMESERVER) ; //#define IPPORT_TIMESERVER 37
39. sa.sin_addr.S_un.S_addr = ::inet_addr(lpRemote) ;
40. if (sa.sin_addr.S_un.S_addr == INADDR_NONE)
41. {
42. HOSTENT* host = gethostbyname(lpRemote);
43. if (NULL == host)
44. {
45. goto END;
46. }
47. sa.sin_addr.S_un.S_addr = *(u_long *)host->h_addr_list[0];
48. }
49. if(::connect(skt, (SOCKADDR*) &sa, sizeof(sa)) == SOCKET_ERROR)
50. {
51. goto END;
52. }
53. int iResult;
54. u_long ulTime;
55. iResult = recv(skt, (char*)&ulTime, 4, 0);
56. //同步係統時間
57. if ( iResult>0 )
58. {
59. ulTime = ::ntohl(ulTime);
60. SetLocalSystemTime(ulTime);
61. }
62.END:
63. closesocket(skt);
64. ::WSACleanup();
65. return ret;
66.}
void SetLocalSystemTime(u_long ulTime)
{
FILETIME ftNew ;
SYSTEMTIME stOld, stNew ;
::GetLocalTime (&stOld) ; //首先取得目前的本地时间
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 * ulTime;
ftNew = * (FILETIME *) &li;
::FileTimeToSystemTime (&ftNew, &stNew);
::SetSystemTime (&stNew);
}
bool SetSystemFromSocket(LPCSTR lpRemote)
{
bool ret = true;
WSADATA WSAData;
::WSAStartup (MAKEWORD(2,2), &WSAData);
SOCKET skt=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TCHAR msg[512];
if (skt == INVALID_SOCKET)
{
goto END;
}
struct sockaddr_in sa ;
sa.sin_family = AF_INET ;
sa.sin_port = ::htons (IPPORT_TIMESERVER) ; //#define IPPORT_TIMESERVER 37
sa.sin_addr.S_un.S_addr = ::inet_addr(lpRemote) ;
if (sa.sin_addr.S_un.S_addr == INADDR_NONE)
{
HOSTENT* host = gethostbyname(lpRemote);
if (NULL == host)
{
goto END;
}
sa.sin_addr.S_un.S_addr = *(u_long *)host->h_addr_list[0];
}
if(::connect(skt, (SOCKADDR*) &sa, sizeof(sa)) == SOCKET_ERROR)
{
goto END;
}
int iResult;
u_long ulTime;
iResult = recv(skt, (char*)&ulTime, 4, 0);
//同步係統時間
if ( iResult>0 )
{
ulTime = ::ntohl(ulTime);
SetLocalSystemTime(ulTime);
}
END:
closesocket(skt);
::WSACleanup();
return ret;
}
2.网络校时协议(NTP)
Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。
NTP协议格式:
NTP packet = NTP header + Four TimeStamps = 48byte NTP header : 16byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- |LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
LeapYearIndicator : 2bit
VersionNumber : 3bit
Stratum : 8bit
Mode : 3 bit
PollInterval : 8 bit
Percision : 8bit | Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root delay : 32bit | Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root Dispersion : 32bit | Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Identifier : 32bit Four TimeStamps : 32byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | Reference Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Timestamp : 64bit | Originate Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Originate Timestamp : 64bit | Receive Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Receive Timestamp : 64bit | Transmit Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Transmit Timestamp : 64bit | Authenticator (optional) (96) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- * LI:跳跃指示器,警告在当月最后一天的最终时刻插入的迫近闺秒(闺秒)。
* VN:版本号。
* Mode:模式。该字段包括以下值:0-预留;1-对称行为;3-客户机;4-服务器;5-广播;6-NTP 控制信息
* Stratum:对本地时钟级别的整体识别。
* Poll:有符号整数表示连续信息间的最大间隔。
* Precision:有符号整数表示本地时钟精确度。
* Root Delay:有符号固定点序号表示主要参考源的总延迟,很短时间内的位15到16间的分段点。
* Root Dispersion:无符号固定点序号表示相对于主要参考源的正常差错,很短时间内的位15到16间的分段点。
* Reference Identifier:识别特殊参考源。
* Originate Timestamp:这是向服务器请求分离客户机的时间,采用64位时标(Timestamp)格式。
* Receive Timestamp:这是向服务器请求到达客户机的时间,采用64位时标(Timestamp)格式。
* Transmit Timestamp:这是向客户机答复分离服务器的时间,采用64位时标(Timestamp)格式。
* Authenticator(Optional):当实现了 NTP 认证模式,主要标识符和信息数字域就包括已定义的信息认证代码(MAC)信息。 配置NTP服务器:
1)、Linux主机做时间服务器(以RedHat9.0为例)
第一步:检查是否已经安装有ntp软件包。输入“rpm -qa|grep ntp”,如果已经安装应该显示“ntp-4.1.2-0.rc1”。
第二步:安装ntp软件,从ftp://ftp.redhat.com下载rpm包,输入“rpm -ivh ntp-xxx.rpm”执行安装。
第三步:配置ntp服务。备份原/etc/ntp.conf文件后,输入以下内容
server pool.ntp.org
server pool.ntp.org
server pool.ntp.org
driftfile /etc/ntp/drift
三行server都设pool.ntp.org是为了提供连接冗余,当第一个地址连接失败时,后面的地址提供时间服务,注意这里的pool.ntp.org对应一组IP地址,由DNS随机分配。
第四步:启动ntp服务。输入“service ntp restart”。
为了保证以后Linux机启动后ntp服务能自动启动,还要输入“chkconfig ntpd on”。Linux下的ntp软件不但能自动与互联网上的时钟保持同步,同时本身已经是一台SNTP服务器了,可以供局域网内的电脑校对时间。建议启动 NTP服务后,先用date命令手工校正一下时间,以后系统会自动与互联网上的主时间服务器保持同步。ntp服务还有一个好处,如果当前系统的时间与标准时间有所误差,它不是马上把时间校正,而是逐步缩小与标准时间的误差,以免系统内部出现时间突变。 2)、Windows2000、XP做时间服务器
第一步:指定主时间服务器。在DOS方式输入“net time /setsntp:pool.ntp.org”,这里我们指定pool.ntp.org是主时间服务器,也可以是其它地址。
第二步:开始与主时间服务器同步。先关闭windows time服务,再开启该服务。可以在“管理工具”的“服务”界面下完成,也可以以DOS方式输入“net stop w32time”、“net start w32time”。
第三步:设置电脑的Windows time服务的启动方式为自动。在“管理工具”的“服务”界面下完成。
注意这台windows主机不能加入任何域,否则无法启动windows time服务。此时,这台windows电脑已经是互联上主时间服务器的客户了,以后每次电脑启动时,都会自动与主时间服务器校对时间。如果网络不通,电脑也会过45分钟后再次自动校对时间。需要注意的是电脑的时钟与标准时间误差不能超过12小时,否则不能自动校对,而要手动校正了。
第四步:使这台电脑成为时间服务器,供局域网内部的电脑校对时间。用“regedit”打开注册表,把 “HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeParameters”中的 LocalNTP改为1即可。 3)、Windows98做时间服务器
一般不推荐Windows98系统做时间服务器,而且win98本身也不含时间服务器功能,需要安装第三方软件。 客户端时间同步代码:view plaincopy to clipboardprint?
01.#include
02.#include
03.#include
04.#include
05.#pragma comment(lib, "Ws2_32.lib")
06.typedef struct ntp {
07. char Flag;
08. char PeerClockStratum;
09. char PeerPollingInterval;
10. char PeerClockPrecision;
11. char RootDelay[4];
12. char ClockDispersion[4];
13. char ReferenceClock[4];
14. char ReferenceClockUpdateTime[8];
15. char OriginateTimeStamp[8];
16. char ReceiveTimeStamp[8];
17. char TransmitTimeStamp[8];
18.} tagNTP;
19.BOOL SetNewTime(WORD year,WORD month,WORD day,WORD hour, WORD minutes,WORD second)
20.{
21. SYSTEMTIME st;
22. GetSystemTime(&st);
23. st.wYear=year+1900; //调整日期和时间
24. st.wMonth=month+1;
25. st.wDay =day;
26. st.wHour =hour;
27. st.wMinute =minutes;
28. st.wSecond =second;
29. if (!SetLocalTime(&st))
30. return FALSE;
31. return TRUE;
32.}
33.void main()
34.{
35. WSADATA wsaData;
36. SOCKET SendSocket;
37. sockaddr_in RecvAddr;
38. //Receive Data
39. sockaddr_in SenderAddr;
40. int SenderAddrSize = sizeof(SenderAddr);
41. ntp SendBuf;
42. int Port = IPPORT_NTP; //#define IPPORT_NTP 123
43. //以下变量的赋值均来源于NTP数据包,你可以用Ethereal抓包
44. SendBuf.Flag =0x1b;
45. SendBuf.PeerClockStratum =0x00;
46. SendBuf.PeerPollingInterval =0x00;
47. SendBuf.PeerClockPrecision =0x00;
48. memset(SendBuf.RootDelay ,0,4);
49. memset(SendBuf.ClockDispersion,0,4);
50. memset(SendBuf.ReferenceClock,0,4);
51. memset(SendBuf.ReferenceClockUpdateTime,0,8);
52. memset(SendBuf.OriginateTimeStamp,0,8);
53. memset(SendBuf.ReceiveTimeStamp,0,8);
54. memcpy(&SendBuf.TransmitTimeStamp[0],"0xc7",1);
55. memcpy(&SendBuf.TransmitTimeStamp[1],"0x50",1);
56. memcpy(&SendBuf.TransmitTimeStamp[2],"0xe7",1);
57. memcpy(&SendBuf.TransmitTimeStamp[3],"0xa0",1);
58. SendBuf.TransmitTimeStamp[4]=0x00;
59. SendBuf.TransmitTimeStamp[5]=0x00;
60. SendBuf.TransmitTimeStamp[6]=0x00;
61. SendBuf.TransmitTimeStamp[7]=0x00;
62. int BufLen = 48; //包的长度为48字节
63. tm *newtime;
64. time_t long_time;
65. WSAStartup(MAKEWORD(2,2), &wsaData);
66. //---------------------------------------------
67. // Create a socket for sending data
68. SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
69. RecvAddr.sin_family = AF_INET;
70. RecvAddr.sin_port = htons(Port);
71. RecvAddr.sin_addr.s_addr = inet_addr("128.101.1.241"); //NTP服务器的地址
72. sendto(SendSocket,
73. (char *)&SendBuf,
74. BufLen,
75. 0,
76. (SOCKADDR *) &RecvAddr,
77. sizeof(RecvAddr));
78. /*开始接收发过来的数据*/
79. printf("Receiving datagrams...\n");
80. recvfrom(SendSocket,
81. (char *)&SendBuf,
82. BufLen,
83. 0,
84. (SOCKADDR *)&SenderAddr,
85. &SenderAddrSize);
86. printf("Finished receiving.Closing socket.\n");
87. closesocket(SendSocket);
88. //*********************************************
89. memcpy(&long_time,SendBuf.ReceiveTimeStamp,4); //从收到的包里面取出前32位放入变量long_time中
90. printf("%d\n",long_time);
91. long_time = ntohl(long_time)-2208988800;//把低位的字节和高位字节互换
92. newtime = localtime(&long_time); /* Convert to local time. */
93. SetNewTime(newtime->tm_year,
94. newtime->tm_mon ,
95. newtime->tm_mday ,
96. newtime->tm_hour ,
97. newtime->tm_min,
98. newtime->tm_sec );
99. //---------------------------------------------
100. // Clean up and quit.
101. //---------------------------------------------
102. printf("OK,Exiting.\n");
103. WSACleanup();
104. return;
105.}
#include
#include
#include
#include
#pragma comment(lib, "Ws2_32.lib")
typedef struct ntp {
char Flag;
char PeerClockStratum;
char PeerPollingInterval;
char PeerClockPrecision;
char RootDelay[4];
char ClockDispersion[4];
char ReferenceClock[4];
char ReferenceClockUpdateTime[8];
char OriginateTimeStamp[8];
char ReceiveTimeStamp[8];
char TransmitTimeStamp[8];
} tagNTP;
BOOL SetNewTime(WORD year,WORD month,WORD day,WORD hour, WORD minutes,WORD second)
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear=year+1900; //调整日期和时间
st.wMonth=month+1;
st.wDay =day;
st.wHour =hour;
st.wMinute =minutes;
st.wSecond =second;
if (!SetLocalTime(&st))
return FALSE;
return TRUE;
}
void main()
{
WSADATA wsaData;
SOCKET SendSocket;
sockaddr_in RecvAddr;
//Receive Data
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
ntp SendBuf;
int Port = IPPORT_NTP; //#define IPPORT_NTP 123
//以下变量的赋值均来源于NTP数据包,你可以用Ethereal抓包
SendBuf.Flag =0x1b;
SendBuf.PeerClockStratum =0x00;
SendBuf.PeerPollingInterval =0x00;
SendBuf.PeerClockPrecision =0x00;
memset(SendBuf.RootDelay ,0,4);
memset(SendBuf.ClockDispersion,0,4);
memset(SendBuf.ReferenceClock,0,4);
memset(SendBuf.ReferenceClockUpdateTime,0,8);
memset(SendBuf.OriginateTimeStamp,0,8);
memset(SendBuf.ReceiveTimeStamp,0,8);
memcpy(&SendBuf.TransmitTimeStamp[0],"0xc7",1);
memcpy(&SendBuf.TransmitTimeStamp[1],"0x50",1);
memcpy(&SendBuf.TransmitTimeStamp[2],"0xe7",1);
memcpy(&SendBuf.TransmitTimeStamp[3],"0xa0",1);
SendBuf.TransmitTimeStamp[4]=0x00;
SendBuf.TransmitTimeStamp[5]=0x00;
SendBuf.TransmitTimeStamp[6]=0x00;
SendBuf.TransmitTimeStamp[7]=0x00;
int BufLen = 48; //包的长度为48字节
tm *newtime;
time_t long_time;
WSAStartup(MAKEWORD(2,2), &wsaData);
//---------------------------------------------
// Create a socket for sending data
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("128.101.1.241"); //NTP服务器的地址
sendto(SendSocket,
(char *)&SendBuf,
BufLen,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr));
/*开始接收发过来的数据*/
printf("Receiving datagrams...\n");
recvfrom(SendSocket,
(char *)&SendBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
printf("Finished receiving.Closing socket.\n");
closesocket(SendSocket);
//*********************************************
memcpy(&long_time,SendBuf.ReceiveTimeStamp,4); //从收到的包里面取出前32位放入变量long_time中
printf("%d\n",long_time);
long_time = ntohl(long_time)-2208988800;//把低位的字节和高位字节互换
newtime = localtime(&long_time); /* Convert to local time. */
SetNewTime(newtime->tm_year,
newtime->tm_mon ,
newtime->tm_mday ,
newtime->tm_hour ,
newtime->tm_min,
newtime->tm_sec );
//---------------------------------------------
// Clean up and quit.
//---------------------------------------------
printf("OK,Exiting.\n");
WSACleanup();
return;
} 3.NetRemoteTOD API函数 NetRemoteTOD可以返回指定服务器的时间,具体说明见MSDN.
利用这个API函数有个限制,那就是客户端必须要有对服务器的访问权限(你可以先通过局域网访问这台服务器,然后记住访问密码,再用这个函数访问就不会有问题了),否则函数会返回权限拒绝错误.
NetRemoteTOD示例:view plaincopy to clipboardprint?
01.#include
02.#include
03.#include
04.int wmain(int argc, wchar_t *argv[])
05.{
06. LPTIME_OF_DAY_INFO pBuf = NULL;
07. NET_API_STATUS nStatus;
08. LPTSTR pszServerName = NULL;
09. if (argc > 2)
10. {
11. fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
12. exit(1);
13. }
14. // The server is not the default local computer.
15. //
16. if (argc == 2)
17. pszServerName = argv[1];
18. //
19. // Call the NetRemoteTOD function.
20. //
21. nStatus = NetRemoteTOD(pszServerName,
22. (LPBYTE *)&pBuf);
23. //
24. // If the function succeeds, display the current date and time.
25. //
26. if (nStatus == NERR_Success)
27. {
28. if (pBuf != NULL)
29. {
30. fprintf(stderr, "\nThe current date is: %d/%d/%d\n",
31. pBuf->tod_month, pBuf->tod_day, pBuf->tod_year);
32. fprintf(stderr, "The current time is: %d:%d:%d\n",
33. pBuf->tod_hours, pBuf->tod_mins, pBuf->tod_secs);
34. }
35. }
36. //
37. // Otherwise, display a system error.
38. else
39. fprintf(stderr, "A system error has occurred: %d\n", nStatus);
40. //
41. // Free the allocated buffer.
42. //
43. if (pBuf != NULL)
44. NetApiBufferFree(pBuf);
45. return 0;
46.}
#include
#include
#include
int wmain(int argc, wchar_t *argv[])
{
LPTIME_OF_DAY_INFO pBuf = NULL;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;
if (argc > 2)
{
fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
exit(1);
}
// The server is not the default local computer.
//
if (argc == 2)
pszServerName = argv[1];
//
// Call the NetRemoteTOD function.
//
nStatus = NetRemoteTOD(pszServerName,
(LPBYTE *)&pBuf);
//
// If the function succeeds, display the current date and time.
//
if (nStatus == NERR_Success)
{
if (pBuf != NULL)
{
fprintf(stderr, "\nThe current date is: %d/%d/%d\n",
pBuf->tod_month, pBuf->tod_day, pBuf->tod_year);
fprintf(stderr, "The current time is: %d:%d:%d\n",
pBuf->tod_hours, pBuf->tod_mins, pBuf->tod_secs);
}
}
//
// Otherwise, display a system error.
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
//
// Free the allocated buffer.
//
if (pBuf != NULL)
NetApiBufferFree(pBuf);
return 0;
} 4.其他方法
如果条件允许的话,我们可以自己写服务器端程式来返回需要的服务器端时间,然后在客户端写socket来接收时间信息.
还有一种更简单的方法就是向服务器上写一个文件,然后读取这个文件的创建日期来获得服务器的时间,这种方法可能精确性不是很高,而且需要对服务器有写文件的权限
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/study_live/archive/2009/12/23/5060883.aspx
二 工作组环境
1)如果所有机器都可以访问internet,可以直接使用time.windows.com(默认的配置)
2)如果机器不能访问internet,或者有防火墙导致无法同步,可以在2003服务器上创建时间服务器,客户端XP系统设置时间服务器地址为2003服务器。
三 客户端设置
双击托盘区显示时间的地方,出现对话框之后选择Internet时间设置时间服务器的地址。默认为time.windows.com,设置为2003服务器地址,然后单击“立即更新”按钮实现“时间同步”。
四 服务器端设置
1. 单击“开始”,单击“运行”,键入 regedit,然后单击“确定”。
2. 找到并单击下面的注册表子项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config\AnnounceFlags
3. 在右窗格中,右键单击“AnnounceFlags”,然后单击“修改”。
4. 在“编辑 DWORD 值”的“数值数据”框中键入 A,然后单击“确定”。
5. 退出注册表编辑器。
6. 在命令提示符处,键入以下命令以重新启动 Windows 时间服务,然后按 Enter:
net stop w32time && net start w32time
最近因工作原因,需要客户端计算机与FTP服务器时间上进行同步,上网搜集了些时间同步的方法记录下来, 以备不需之用!1.时间协议(TIME protocol)
时间协议(TIME protocol)是一个在RFC 868内定义的网络协议。它用作提供机器可读的日期时间资讯。
时间协议可以在TCP或UDP上使用。在TCP上,主机会连接支援时间协议的服务器的TCP埠 37。服务器会传送32位二进制数字然后断开连接,数字表示由格林威治时间1900年1月1日午夜0时0分0秒至当时的总秒数。主机在接收到时间后断开连接。
在UDP上,客户端会每送一个(通常为空的)数据包到UDP埠 37。服务器会把包含时间的数据包传回。在过程中没有进行连线。
现时,时间协议已经被网络时间协议(Network Time Protocol,NTP)所取代。
使用时间协议需要在服务器端开启时间服务,目前在windows中我还没找到系统自带的开启时间服务的方法, 但网络上有些小软件可以帮助实现(如NetTime网络时标, 它支持Time,NTP等好几种协议, 可惜需要注册使用).
基于时间协议客户端实现代码:view plaincopy to clipboardprint?
01.void SetLocalSystemTime(u_long ulTime)
02.{
03. FILETIME ftNew ;
04. SYSTEMTIME stOld, stNew ;
05. ::GetLocalTime (&stOld) ; //首先取得目前的本地时间
06. stNew.wYear = 1900 ;
07. stNew.wMonth = 1 ;
08. stNew.wDay = 1 ;
09. stNew.wHour = 0 ;
10. stNew.wMinute = 0 ;
11. stNew.wSecond = 0 ;
12. stNew.wMilliseconds = 0 ;
13. ::SystemTimeToFileTime (&stNew, &ftNew);
14. /* 将SYSTEMTIME结构设定为1900年1月1日午夜(0时)。
15. 并将这个SYSTEMTIME结构传递给SystemTimeToFileTime,将此结构转化为FILETIME结构。
16. FILETIME实际上只是由两个32位元的DWORD一起组成64位元的整数,
17. 用来表示从1601年1月1日至今间隔为100奈秒(nanosecond)的间隔数。 */
18. LARGE_INTEGER li ; //64位大整数
19. li = * (LARGE_INTEGER *) &ftNew;
20. li.QuadPart += (LONGLONG) 10000000 * ulTime;
21. ftNew = * (FILETIME *) &li;
22. ::FileTimeToSystemTime (&ftNew, &stNew);
23. ::SetSystemTime (&stNew);
24.}
25.bool SetSystemFromSocket(LPCSTR lpRemote)
26.{
27. bool ret = true;
28. WSADATA WSAData;
29. ::WSAStartup (MAKEWORD(2,2), &WSAData);
30. SOCKET skt=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
31. TCHAR msg[512];
32. if (skt == INVALID_SOCKET)
33. {
34. goto END;
35. }
36. struct sockaddr_in sa ;
37. sa.sin_family = AF_INET ;
38. sa.sin_port = ::htons (IPPORT_TIMESERVER) ; //#define IPPORT_TIMESERVER 37
39. sa.sin_addr.S_un.S_addr = ::inet_addr(lpRemote) ;
40. if (sa.sin_addr.S_un.S_addr == INADDR_NONE)
41. {
42. HOSTENT* host = gethostbyname(lpRemote);
43. if (NULL == host)
44. {
45. goto END;
46. }
47. sa.sin_addr.S_un.S_addr = *(u_long *)host->h_addr_list[0];
48. }
49. if(::connect(skt, (SOCKADDR*) &sa, sizeof(sa)) == SOCKET_ERROR)
50. {
51. goto END;
52. }
53. int iResult;
54. u_long ulTime;
55. iResult = recv(skt, (char*)&ulTime, 4, 0);
56. //同步係統時間
57. if ( iResult>0 )
58. {
59. ulTime = ::ntohl(ulTime);
60. SetLocalSystemTime(ulTime);
61. }
62.END:
63. closesocket(skt);
64. ::WSACleanup();
65. return ret;
66.}
void SetLocalSystemTime(u_long ulTime)
{
FILETIME ftNew ;
SYSTEMTIME stOld, stNew ;
::GetLocalTime (&stOld) ; //首先取得目前的本地时间
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 * ulTime;
ftNew = * (FILETIME *) &li;
::FileTimeToSystemTime (&ftNew, &stNew);
::SetSystemTime (&stNew);
}
bool SetSystemFromSocket(LPCSTR lpRemote)
{
bool ret = true;
WSADATA WSAData;
::WSAStartup (MAKEWORD(2,2), &WSAData);
SOCKET skt=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TCHAR msg[512];
if (skt == INVALID_SOCKET)
{
goto END;
}
struct sockaddr_in sa ;
sa.sin_family = AF_INET ;
sa.sin_port = ::htons (IPPORT_TIMESERVER) ; //#define IPPORT_TIMESERVER 37
sa.sin_addr.S_un.S_addr = ::inet_addr(lpRemote) ;
if (sa.sin_addr.S_un.S_addr == INADDR_NONE)
{
HOSTENT* host = gethostbyname(lpRemote);
if (NULL == host)
{
goto END;
}
sa.sin_addr.S_un.S_addr = *(u_long *)host->h_addr_list[0];
}
if(::connect(skt, (SOCKADDR*) &sa, sizeof(sa)) == SOCKET_ERROR)
{
goto END;
}
int iResult;
u_long ulTime;
iResult = recv(skt, (char*)&ulTime, 4, 0);
//同步係統時間
if ( iResult>0 )
{
ulTime = ::ntohl(ulTime);
SetLocalSystemTime(ulTime);
}
END:
closesocket(skt);
::WSACleanup();
return ret;
}
2.网络校时协议(NTP)
Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。
NTP协议格式:
NTP packet = NTP header + Four TimeStamps = 48byte NTP header : 16byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- |LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
LeapYearIndicator : 2bit
VersionNumber : 3bit
Stratum : 8bit
Mode : 3 bit
PollInterval : 8 bit
Percision : 8bit | Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root delay : 32bit | Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root Dispersion : 32bit | Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Identifier : 32bit Four TimeStamps : 32byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | Reference Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Timestamp : 64bit | Originate Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Originate Timestamp : 64bit | Receive Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Receive Timestamp : 64bit | Transmit Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Transmit Timestamp : 64bit | Authenticator (optional) (96) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- * LI:跳跃指示器,警告在当月最后一天的最终时刻插入的迫近闺秒(闺秒)。
* VN:版本号。
* Mode:模式。该字段包括以下值:0-预留;1-对称行为;3-客户机;4-服务器;5-广播;6-NTP 控制信息
* Stratum:对本地时钟级别的整体识别。
* Poll:有符号整数表示连续信息间的最大间隔。
* Precision:有符号整数表示本地时钟精确度。
* Root Delay:有符号固定点序号表示主要参考源的总延迟,很短时间内的位15到16间的分段点。
* Root Dispersion:无符号固定点序号表示相对于主要参考源的正常差错,很短时间内的位15到16间的分段点。
* Reference Identifier:识别特殊参考源。
* Originate Timestamp:这是向服务器请求分离客户机的时间,采用64位时标(Timestamp)格式。
* Receive Timestamp:这是向服务器请求到达客户机的时间,采用64位时标(Timestamp)格式。
* Transmit Timestamp:这是向客户机答复分离服务器的时间,采用64位时标(Timestamp)格式。
* Authenticator(Optional):当实现了 NTP 认证模式,主要标识符和信息数字域就包括已定义的信息认证代码(MAC)信息。 配置NTP服务器:
1)、Linux主机做时间服务器(以RedHat9.0为例)
第一步:检查是否已经安装有ntp软件包。输入“rpm -qa|grep ntp”,如果已经安装应该显示“ntp-4.1.2-0.rc1”。
第二步:安装ntp软件,从ftp://ftp.redhat.com下载rpm包,输入“rpm -ivh ntp-xxx.rpm”执行安装。
第三步:配置ntp服务。备份原/etc/ntp.conf文件后,输入以下内容
server pool.ntp.org
server pool.ntp.org
server pool.ntp.org
driftfile /etc/ntp/drift
三行server都设pool.ntp.org是为了提供连接冗余,当第一个地址连接失败时,后面的地址提供时间服务,注意这里的pool.ntp.org对应一组IP地址,由DNS随机分配。
第四步:启动ntp服务。输入“service ntp restart”。
为了保证以后Linux机启动后ntp服务能自动启动,还要输入“chkconfig ntpd on”。Linux下的ntp软件不但能自动与互联网上的时钟保持同步,同时本身已经是一台SNTP服务器了,可以供局域网内的电脑校对时间。建议启动 NTP服务后,先用date命令手工校正一下时间,以后系统会自动与互联网上的主时间服务器保持同步。ntp服务还有一个好处,如果当前系统的时间与标准时间有所误差,它不是马上把时间校正,而是逐步缩小与标准时间的误差,以免系统内部出现时间突变。 2)、Windows2000、XP做时间服务器
第一步:指定主时间服务器。在DOS方式输入“net time /setsntp:pool.ntp.org”,这里我们指定pool.ntp.org是主时间服务器,也可以是其它地址。
第二步:开始与主时间服务器同步。先关闭windows time服务,再开启该服务。可以在“管理工具”的“服务”界面下完成,也可以以DOS方式输入“net stop w32time”、“net start w32time”。
第三步:设置电脑的Windows time服务的启动方式为自动。在“管理工具”的“服务”界面下完成。
注意这台windows主机不能加入任何域,否则无法启动windows time服务。此时,这台windows电脑已经是互联上主时间服务器的客户了,以后每次电脑启动时,都会自动与主时间服务器校对时间。如果网络不通,电脑也会过45分钟后再次自动校对时间。需要注意的是电脑的时钟与标准时间误差不能超过12小时,否则不能自动校对,而要手动校正了。
第四步:使这台电脑成为时间服务器,供局域网内部的电脑校对时间。用“regedit”打开注册表,把 “HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeParameters”中的 LocalNTP改为1即可。 3)、Windows98做时间服务器
一般不推荐Windows98系统做时间服务器,而且win98本身也不含时间服务器功能,需要安装第三方软件。 客户端时间同步代码:view plaincopy to clipboardprint?
01.#include
02.#include
03.#include
04.#include
05.#pragma comment(lib, "Ws2_32.lib")
06.typedef struct ntp {
07. char Flag;
08. char PeerClockStratum;
09. char PeerPollingInterval;
10. char PeerClockPrecision;
11. char RootDelay[4];
12. char ClockDispersion[4];
13. char ReferenceClock[4];
14. char ReferenceClockUpdateTime[8];
15. char OriginateTimeStamp[8];
16. char ReceiveTimeStamp[8];
17. char TransmitTimeStamp[8];
18.} tagNTP;
19.BOOL SetNewTime(WORD year,WORD month,WORD day,WORD hour, WORD minutes,WORD second)
20.{
21. SYSTEMTIME st;
22. GetSystemTime(&st);
23. st.wYear=year+1900; //调整日期和时间
24. st.wMonth=month+1;
25. st.wDay =day;
26. st.wHour =hour;
27. st.wMinute =minutes;
28. st.wSecond =second;
29. if (!SetLocalTime(&st))
30. return FALSE;
31. return TRUE;
32.}
33.void main()
34.{
35. WSADATA wsaData;
36. SOCKET SendSocket;
37. sockaddr_in RecvAddr;
38. //Receive Data
39. sockaddr_in SenderAddr;
40. int SenderAddrSize = sizeof(SenderAddr);
41. ntp SendBuf;
42. int Port = IPPORT_NTP; //#define IPPORT_NTP 123
43. //以下变量的赋值均来源于NTP数据包,你可以用Ethereal抓包
44. SendBuf.Flag =0x1b;
45. SendBuf.PeerClockStratum =0x00;
46. SendBuf.PeerPollingInterval =0x00;
47. SendBuf.PeerClockPrecision =0x00;
48. memset(SendBuf.RootDelay ,0,4);
49. memset(SendBuf.ClockDispersion,0,4);
50. memset(SendBuf.ReferenceClock,0,4);
51. memset(SendBuf.ReferenceClockUpdateTime,0,8);
52. memset(SendBuf.OriginateTimeStamp,0,8);
53. memset(SendBuf.ReceiveTimeStamp,0,8);
54. memcpy(&SendBuf.TransmitTimeStamp[0],"0xc7",1);
55. memcpy(&SendBuf.TransmitTimeStamp[1],"0x50",1);
56. memcpy(&SendBuf.TransmitTimeStamp[2],"0xe7",1);
57. memcpy(&SendBuf.TransmitTimeStamp[3],"0xa0",1);
58. SendBuf.TransmitTimeStamp[4]=0x00;
59. SendBuf.TransmitTimeStamp[5]=0x00;
60. SendBuf.TransmitTimeStamp[6]=0x00;
61. SendBuf.TransmitTimeStamp[7]=0x00;
62. int BufLen = 48; //包的长度为48字节
63. tm *newtime;
64. time_t long_time;
65. WSAStartup(MAKEWORD(2,2), &wsaData);
66. //---------------------------------------------
67. // Create a socket for sending data
68. SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
69. RecvAddr.sin_family = AF_INET;
70. RecvAddr.sin_port = htons(Port);
71. RecvAddr.sin_addr.s_addr = inet_addr("128.101.1.241"); //NTP服务器的地址
72. sendto(SendSocket,
73. (char *)&SendBuf,
74. BufLen,
75. 0,
76. (SOCKADDR *) &RecvAddr,
77. sizeof(RecvAddr));
78. /*开始接收发过来的数据*/
79. printf("Receiving datagrams...\n");
80. recvfrom(SendSocket,
81. (char *)&SendBuf,
82. BufLen,
83. 0,
84. (SOCKADDR *)&SenderAddr,
85. &SenderAddrSize);
86. printf("Finished receiving.Closing socket.\n");
87. closesocket(SendSocket);
88. //*********************************************
89. memcpy(&long_time,SendBuf.ReceiveTimeStamp,4); //从收到的包里面取出前32位放入变量long_time中
90. printf("%d\n",long_time);
91. long_time = ntohl(long_time)-2208988800;//把低位的字节和高位字节互换
92. newtime = localtime(&long_time); /* Convert to local time. */
93. SetNewTime(newtime->tm_year,
94. newtime->tm_mon ,
95. newtime->tm_mday ,
96. newtime->tm_hour ,
97. newtime->tm_min,
98. newtime->tm_sec );
99. //---------------------------------------------
100. // Clean up and quit.
101. //---------------------------------------------
102. printf("OK,Exiting.\n");
103. WSACleanup();
104. return;
105.}
#include
#include
#include
#include
#pragma comment(lib, "Ws2_32.lib")
typedef struct ntp {
char Flag;
char PeerClockStratum;
char PeerPollingInterval;
char PeerClockPrecision;
char RootDelay[4];
char ClockDispersion[4];
char ReferenceClock[4];
char ReferenceClockUpdateTime[8];
char OriginateTimeStamp[8];
char ReceiveTimeStamp[8];
char TransmitTimeStamp[8];
} tagNTP;
BOOL SetNewTime(WORD year,WORD month,WORD day,WORD hour, WORD minutes,WORD second)
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear=year+1900; //调整日期和时间
st.wMonth=month+1;
st.wDay =day;
st.wHour =hour;
st.wMinute =minutes;
st.wSecond =second;
if (!SetLocalTime(&st))
return FALSE;
return TRUE;
}
void main()
{
WSADATA wsaData;
SOCKET SendSocket;
sockaddr_in RecvAddr;
//Receive Data
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
ntp SendBuf;
int Port = IPPORT_NTP; //#define IPPORT_NTP 123
//以下变量的赋值均来源于NTP数据包,你可以用Ethereal抓包
SendBuf.Flag =0x1b;
SendBuf.PeerClockStratum =0x00;
SendBuf.PeerPollingInterval =0x00;
SendBuf.PeerClockPrecision =0x00;
memset(SendBuf.RootDelay ,0,4);
memset(SendBuf.ClockDispersion,0,4);
memset(SendBuf.ReferenceClock,0,4);
memset(SendBuf.ReferenceClockUpdateTime,0,8);
memset(SendBuf.OriginateTimeStamp,0,8);
memset(SendBuf.ReceiveTimeStamp,0,8);
memcpy(&SendBuf.TransmitTimeStamp[0],"0xc7",1);
memcpy(&SendBuf.TransmitTimeStamp[1],"0x50",1);
memcpy(&SendBuf.TransmitTimeStamp[2],"0xe7",1);
memcpy(&SendBuf.TransmitTimeStamp[3],"0xa0",1);
SendBuf.TransmitTimeStamp[4]=0x00;
SendBuf.TransmitTimeStamp[5]=0x00;
SendBuf.TransmitTimeStamp[6]=0x00;
SendBuf.TransmitTimeStamp[7]=0x00;
int BufLen = 48; //包的长度为48字节
tm *newtime;
time_t long_time;
WSAStartup(MAKEWORD(2,2), &wsaData);
//---------------------------------------------
// Create a socket for sending data
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("128.101.1.241"); //NTP服务器的地址
sendto(SendSocket,
(char *)&SendBuf,
BufLen,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr));
/*开始接收发过来的数据*/
printf("Receiving datagrams...\n");
recvfrom(SendSocket,
(char *)&SendBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
printf("Finished receiving.Closing socket.\n");
closesocket(SendSocket);
//*********************************************
memcpy(&long_time,SendBuf.ReceiveTimeStamp,4); //从收到的包里面取出前32位放入变量long_time中
printf("%d\n",long_time);
long_time = ntohl(long_time)-2208988800;//把低位的字节和高位字节互换
newtime = localtime(&long_time); /* Convert to local time. */
SetNewTime(newtime->tm_year,
newtime->tm_mon ,
newtime->tm_mday ,
newtime->tm_hour ,
newtime->tm_min,
newtime->tm_sec );
//---------------------------------------------
// Clean up and quit.
//---------------------------------------------
printf("OK,Exiting.\n");
WSACleanup();
return;
} 3.NetRemoteTOD API函数 NetRemoteTOD可以返回指定服务器的时间,具体说明见MSDN.
利用这个API函数有个限制,那就是客户端必须要有对服务器的访问权限(你可以先通过局域网访问这台服务器,然后记住访问密码,再用这个函数访问就不会有问题了),否则函数会返回权限拒绝错误.
NetRemoteTOD示例:view plaincopy to clipboardprint?
01.#include
02.#include
03.#include
04.int wmain(int argc, wchar_t *argv[])
05.{
06. LPTIME_OF_DAY_INFO pBuf = NULL;
07. NET_API_STATUS nStatus;
08. LPTSTR pszServerName = NULL;
09. if (argc > 2)
10. {
11. fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
12. exit(1);
13. }
14. // The server is not the default local computer.
15. //
16. if (argc == 2)
17. pszServerName = argv[1];
18. //
19. // Call the NetRemoteTOD function.
20. //
21. nStatus = NetRemoteTOD(pszServerName,
22. (LPBYTE *)&pBuf);
23. //
24. // If the function succeeds, display the current date and time.
25. //
26. if (nStatus == NERR_Success)
27. {
28. if (pBuf != NULL)
29. {
30. fprintf(stderr, "\nThe current date is: %d/%d/%d\n",
31. pBuf->tod_month, pBuf->tod_day, pBuf->tod_year);
32. fprintf(stderr, "The current time is: %d:%d:%d\n",
33. pBuf->tod_hours, pBuf->tod_mins, pBuf->tod_secs);
34. }
35. }
36. //
37. // Otherwise, display a system error.
38. else
39. fprintf(stderr, "A system error has occurred: %d\n", nStatus);
40. //
41. // Free the allocated buffer.
42. //
43. if (pBuf != NULL)
44. NetApiBufferFree(pBuf);
45. return 0;
46.}
#include
#include
#include
int wmain(int argc, wchar_t *argv[])
{
LPTIME_OF_DAY_INFO pBuf = NULL;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;
if (argc > 2)
{
fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
exit(1);
}
// The server is not the default local computer.
//
if (argc == 2)
pszServerName = argv[1];
//
// Call the NetRemoteTOD function.
//
nStatus = NetRemoteTOD(pszServerName,
(LPBYTE *)&pBuf);
//
// If the function succeeds, display the current date and time.
//
if (nStatus == NERR_Success)
{
if (pBuf != NULL)
{
fprintf(stderr, "\nThe current date is: %d/%d/%d\n",
pBuf->tod_month, pBuf->tod_day, pBuf->tod_year);
fprintf(stderr, "The current time is: %d:%d:%d\n",
pBuf->tod_hours, pBuf->tod_mins, pBuf->tod_secs);
}
}
//
// Otherwise, display a system error.
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
//
// Free the allocated buffer.
//
if (pBuf != NULL)
NetApiBufferFree(pBuf);
return 0;
} 4.其他方法
如果条件允许的话,我们可以自己写服务器端程式来返回需要的服务器端时间,然后在客户端写socket来接收时间信息.
还有一种更简单的方法就是向服务器上写一个文件,然后读取这个文件的创建日期来获得服务器的时间,这种方法可能精确性不是很高,而且需要对服务器有写文件的权限
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/study_live/archive/2009/12/23/5060883.aspx
与Internet时间服务器同步错误,
无法自动与时间服务器同步
与internet时间服务器同步是出现的问题
时间那里自动与服务器同步不了啦?
WIN2000任务栏没有与“INTERNET时间”同步的设置!
怎样使得个人电脑时间与INTERNET时间同步?
与网络时间同步
cool edit pro!!怎样调整开始时间与伴奏同步?????
怎样设置录音同步?
电脑的时间日期无法与internet服务器同步是什么原因啊?
怎样同步两个服务器数据?
时间不能与Internet同步
时间不能与internet同步
windows时间服务器同步的原理是什么?
请问如何解决XP系统的日期和时间自动与Internet时间服务器同步的错误?
XP下如何设置时钟同步的下次同步时间
数字证书与邮件的绑定中的客户端服务器应怎样查找填写
网游客户端与服务器的关系?
服务器与客户端的数据联接问题?
怎样与pc同步 7610
歌曲与歌词怎样同步
怎样设置才可以使mp3歌词与歌曲同步播放啊?~
在制作幻灯片时怎样将图象与所设置的声音同步?
怎样实现服务器访问客户端,而客户端无法访问服务端?