Nas*_*ine 146
由于旧的已接受的答案被删除(这是一个不再存在的Google代码搜索结果的链接),我想我可以回答这个问题以供将来参考:
public static DateTime GetNetworkTime()
{
    //default Windows time server
    const string ntpServer = "time.windows.com";
    // NTP message size - 16 bytes of the digest (RFC 2030)
    var ntpData = new byte[48];
    //Setting the Leap Indicator, Version Number and Mode values
    ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
    var addresses = Dns.GetHostEntry(ntpServer).AddressList;
    //The UDP port number assigned to NTP is 123
    var ipEndPoint = new IPEndPoint(addresses[0], 123);
    //NTP uses UDP
    using(var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
    {
        socket.Connect(ipEndPoint);
        //Stops code hang if NTP is blocked
        socket.ReceiveTimeout = 3000;     
        socket.Send(ntpData);
        socket.Receive(ntpData);
        socket.Close();
    }
    //Offset to get to the "Transmit Timestamp" field (time at which the reply 
    //departed the server for the client, in 64-bit timestamp format."
    const byte serverReplyTime = 40;
    //Get the seconds part
    ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
    //Get the seconds fraction
    ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
    //Convert From big-endian to little-endian
    intPart = SwapEndianness(intPart);
    fractPart = SwapEndianness(fractPart);
    var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
    //**UTC** time
    var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);
    return networkDateTime.ToLocalTime();
}
// stackoverflow.com/a/3294698/162671
static uint SwapEndianness(ulong x)
{
    return (uint) (((x & 0x000000ff) << 24) +
                   ((x & 0x0000ff00) << 8) +
                   ((x & 0x00ff0000) >> 8) +
                   ((x & 0xff000000) >> 24));
}
注意:您必须添加以下命名空间
using System.Net;
using System.Net.Sockets;
小智 33
这是该函数的优化版本,它消除了对BitConverter函数的依赖,并使其与NETMF(.NET Micro Framework)兼容
public static DateTime GetNetworkTime()
{
    const string ntpServer = "pool.ntp.org";
    var ntpData = new byte[48];
    ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)
    var addresses = Dns.GetHostEntry(ntpServer).AddressList;
    var ipEndPoint = new IPEndPoint(addresses[0], 123);
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    socket.Connect(ipEndPoint);
    socket.Send(ntpData);
    socket.Receive(ntpData);
    socket.Close();
    ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];
    ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];
    var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
    var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
    return networkDateTime;
}
我知道这个主题很老了,但这些工具总是很方便.我已经使用了上面的资源并创建了一个NtpClient版本,它允许异步获取准确的时间,而不是基于事件.
 /// <summary>
/// Represents a client which can obtain accurate time via NTP protocol.
/// </summary>
public class NtpClient
{
    private readonly TaskCompletionSource<DateTime> _resultCompletionSource;
    /// <summary>
    /// Creates a new instance of <see cref="NtpClient"/> class.
    /// </summary>
    public NtpClient()
    {
        _resultCompletionSource = new TaskCompletionSource<DateTime>();
    }
    /// <summary>
    /// Gets accurate time using the NTP protocol with default timeout of 45 seconds.
    /// </summary>
    /// <returns>Network accurate <see cref="DateTime"/> value.</returns>
    public async Task<DateTime> GetNetworkTimeAsync()
    {
        return await GetNetworkTimeAsync(TimeSpan.FromSeconds(45));
    }
    /// <summary>
    /// Gets accurate time using the NTP protocol with default timeout of 45 seconds.
    /// </summary>
    /// <param name="timeoutMs">Operation timeout in milliseconds.</param>
    /// <returns>Network accurate <see cref="DateTime"/> value.</returns>
    public async Task<DateTime> GetNetworkTimeAsync(int timeoutMs)
    {
        return await GetNetworkTimeAsync(TimeSpan.FromMilliseconds(timeoutMs));
    }
    /// <summary>
    /// Gets accurate time using the NTP protocol with default timeout of 45 seconds.
    /// </summary>
    /// <param name="timeout">Operation timeout.</param>
    /// <returns>Network accurate <see cref="DateTime"/> value.</returns>
    public async Task<DateTime> GetNetworkTimeAsync(TimeSpan timeout)
    {
        using (var socket = new DatagramSocket())
        using (var ct = new CancellationTokenSource(timeout))
        {
            ct.Token.Register(() => _resultCompletionSource.TrySetCanceled());
            socket.MessageReceived += OnSocketMessageReceived;
            //The UDP port number assigned to NTP is 123
            await socket.ConnectAsync(new HostName("pool.ntp.org"), "123");
            using (var writer = new DataWriter(socket.OutputStream))
            {
                // NTP message size is 16 bytes of the digest (RFC 2030)
                var ntpBuffer = new byte[48];
                // Setting the Leap Indicator, 
                // Version Number and Mode values
                // LI = 0 (no warning)
                // VN = 3 (IPv4 only)
                // Mode = 3 (Client Mode)
                ntpBuffer[0] = 0x1B;
                writer.WriteBytes(ntpBuffer);
                await writer.StoreAsync();
                var result = await _resultCompletionSource.Task;
                return result;
            }
        }
    }
    private void OnSocketMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
    {
        try
        {
            using (var reader = args.GetDataReader())
            {
                byte[] response = new byte[48];
                reader.ReadBytes(response);
                _resultCompletionSource.TrySetResult(ParseNetworkTime(response));
            }
        }
        catch (Exception ex)
        {
            _resultCompletionSource.TrySetException(ex);
        }
    }
    private static DateTime ParseNetworkTime(byte[] rawData)
    {
        //Offset to get to the "Transmit Timestamp" field (time at which the reply 
        //departed the server for the client, in 64-bit timestamp format."
        const byte serverReplyTime = 40;
        //Get the seconds part
        ulong intPart = BitConverter.ToUInt32(rawData, serverReplyTime);
        //Get the seconds fraction
        ulong fractPart = BitConverter.ToUInt32(rawData, serverReplyTime + 4);
        //Convert From big-endian to little-endian
        intPart = SwapEndianness(intPart);
        fractPart = SwapEndianness(fractPart);
        var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
        //**UTC** time
        DateTime networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);
        return networkDateTime;
    }
    // stackoverflow.com/a/3294698/162671
    private static uint SwapEndianness(ulong x)
    {
        return (uint)(((x & 0x000000ff) << 24) +
                       ((x & 0x0000ff00) << 8) +
                       ((x & 0x00ff0000) >> 8) +
                       ((x & 0xff000000) >> 24));
    }
}
用法:
var ntp = new NtpClient();
var accurateTime = await ntp.GetNetworkTimeAsync(TimeSpan.FromSeconds(10));
修改版本以补偿网络时间并使用DateTime-Ticks进行计算(比毫秒更精确)
public static DateTime GetNetworkTime()
{
  const string NtpServer = "pool.ntp.org";
  const int DaysTo1900 = 1900 * 365 + 95; // 95 = offset for leap-years etc.
  const long TicksPerSecond = 10000000L;
  const long TicksPerDay = 24 * 60 * 60 * TicksPerSecond;
  const long TicksTo1900 = DaysTo1900 * TicksPerDay;
  var ntpData = new byte[48];
  ntpData[0] = 0x1B; // LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)
  var addresses = Dns.GetHostEntry(NtpServer).AddressList;
  var ipEndPoint = new IPEndPoint(addresses[0], 123);
  long pingDuration = Stopwatch.GetTimestamp(); // temp access (JIT-Compiler need some time at first call)
  using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
  {
    socket.Connect(ipEndPoint);
    socket.ReceiveTimeout = 5000;
    socket.Send(ntpData);
    pingDuration = Stopwatch.GetTimestamp(); // after Send-Method to reduce WinSocket API-Call time
    socket.Receive(ntpData);
    pingDuration = Stopwatch.GetTimestamp() - pingDuration;
  }
  long pingTicks = pingDuration * TicksPerSecond / Stopwatch.Frequency;
  // optional: display response-time
  // Console.WriteLine("{0:N2} ms", new TimeSpan(pingTicks).TotalMilliseconds);
  long intPart = (long)ntpData[40] << 24 | (long)ntpData[41] << 16 | (long)ntpData[42] << 8 | ntpData[43];
  long fractPart = (long)ntpData[44] << 24 | (long)ntpData[45] << 16 | (long)ntpData[46] << 8 | ntpData[47];
  long netTicks = intPart * TicksPerSecond + (fractPart * TicksPerSecond >> 32);
  var networkDateTime = new DateTime(TicksTo1900 + netTicks + pingTicks / 2);
  return networkDateTime.ToLocalTime(); // without ToLocalTime() = faster
}