Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准 度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。
NTP采用C/S结构,Server端作为时间来源,可以是原子钟、天文台、卫星,也可以从Internet上获取;而在我们的局域网内,则可以配置一个服务器,将其硬件时间作为时间源来提供服务;我在网上搜索了一下,大部分关于NTP服务的文章都是基于Linux的,提到windows server系列操作系统的不是很多,不过还是有很实用的内容;总结下来,其实要在windows server 2003上配置NTP服务是一件很简单的事情,如果该服务器是域控制器(DC),则已经默认启动了一个叫做win32time的服务,这个服务就是我们的NTPServer;如果不是域控制器,只需要修改注册表HKEY_LOCAL_MACHINE>>SYSTEM>>CurrentControlSet>>Services>>W32Time>>TimeProviders>>NtpServer下的Enabled为1(true)即可强制其宣布自身为可靠的时间源以启动win32time服务。
Client端通过主动连接有效的Server端即可同步本地时间;以下是我在CodeProject上找到的有关NTPClient在C#下实现的代码(原帖地址):
NTPClient
/*
* NTPClient
* Copyright (C)2001 Valer BOCAN
* Last modified: June 29, 2001
* All Rights Reserved
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* To fully understand the concepts used herein, I strongly
* recommend that you read the RFC 2030.
*
* NOTE: This example is intended to be compiled with Visual Studio .NET Beta 2
*/
namespace TimeSync {
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
// Leap indicator field values
public enum _LeapIndicator {
NoWarning, // 0 - No warning
LastMinute61, // 1 - Last minute has 61 seconds
LastMinute59, // 2 - Last minute has 59 seconds
Alarm // 3 - Alarm condition (clock not synchronized)
}
// Stratum field values
public enum _Stratum {
Unspecified, // 0 - unspecified or unavailable
PrimaryReference, // 1 - primary reference (e.g. radio-clock)
SecondaryReference, // 2-15 - secondary reference (via NTP or SNTP)
Reserved // 16-255 - reserved
}
///
/// NTPClient is a C# class designed to connect to time servers on the Internet.
/// The implementation of the protocol is based on the RFC 2030.
///
/// Public class members:
///
/// LeapIndicator - Warns of an impending leap second to be inserted/deleted in the last
/// minute of the current day. (See the _LeapIndicator enum)
///
/// VersionNumber - Version number of the protocol (3 or 4).
///
/// Mode - Returns mode. (See the _Mode enum)
///
/// Stratum - Stratum of the clock. (See the _Stratum enum)
///
/// PollInterval - Maximum interval between successive messages.
///
/// Precision - Precision of the clock.
///
/// RootDelay - Round trip time to the primary reference source.
///
/// RootDispersion - Nominal error relative to the primary reference source.
///
/// ReferenceID - Reference identifier (either a 4 character string or an IP address).
///
/// ReferenceTimestamp - The time at which the clock was last set or corrected.
///
/// OriginateTimestamp - The time at which the request departed the client for the server.
///
/// ReceiveTimestamp - The time at which the request arrived at the server.
///
/// Transmit Timestamp - The time at which the reply departed the server for client.
///
/// RoundTripDelay - The time between the departure of request and arrival of reply.
///
/// LocalClockOffset - The offset of the local clock relative to the primary reference
/// source.
///
/// Initialize - Sets up data structure and prepares for connection.
///
/// Connect - Connects to the time server and populates the data structure.
/// It can also set the system time.
///
/// IsResponseValid - Returns true if received data is valid and if comes from
/// a NTP-compliant time server.
///
/// ToString - Returns a string representation of the object.
///
/// -----------------------------------------------------------------------------
/// Structure of the standard NTP header (as described in RFC 2030)
/// 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) |
/// | |
/// | |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
/// -----------------------------------------------------------------------------
///
/// NTP Timestamp Format (as described in RFC 2030)
/// 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
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | Seconds |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | Seconds Fraction (0-padded) |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
///
public class NTPClient {
// NTP Data Structure Length
private const byte NTPDataLength = 48;
// NTP Data Structure (as described in RFC 2030)
byte[] NTPData = new byte[NTPDataLength];
// Offset constants for timestamps in the data structure
private const byte offReferenceID = 12;
private const byte offReferenceTimestamp = 16;
private const byte offOriginateTimestamp = 24;
private const byte offReceiveTimestamp = 32;
private const byte offTransmitTimestamp = 40;
// Leap Indicator
public _LeapIndicator LeapIndicator {
get {
// Isolate the two most significant bits
byte val = (byte)(NTPData[0] >> 6);
switch (val) {
case 0: return _LeapIndicator.NoWarning;
case 1: return _LeapIndicator.LastMinute61;
case 2: return _LeapIndicator.LastMinute59;
case 3: goto default;
default:
return _LeapIndicator.Alarm;
}
}
}
// Version Number
public byte VersionNumber {
get {
// Isolate bits 3 - 5
byte val = (byte)((NTPData[0] & 0x38) >> 3);
return val;
}
}
// Mode
public _Mode Mode {
get {
// Isolate bits 0 - 3
byte val = (byte)(NTPData[0] & 0x7);
switch (val) {
case 0: goto default;
case 6: goto default;
case 7: goto default;
default:
return _Mode.Unknown;
case 1:
return _Mode.SymmetricActive;
case 2:
return _Mode.SymmetricPassive;
case 3:
return _Mode.Client;
case 4:
return _Mode.Server;
case 5:
return _Mode.Broadcast;
}
}
}
// Stratum
public _Stratum Stratum {
get {
byte val = (byte)NTPData[1];
if (val == 0) return _Stratum.Unspecified;
else
if (val == 1) return _Stratum.PrimaryReference;
else
if (val