NTP/SNTP时间同步参考

Over the last week of so I've noticed several questions in the newsgroups about how to synchronize a CE device's time with a time server.  Once again, it's not something I'd done, but I knew there were servers out there that provide the time publicly, so it couldn't bee too tough.

First stop was to see if Wikipedia gave a simple explanation.  Useful, but not exactly what we need - we want to know exactly what the server expects, and what exactly it returns.  It does give us the RFCs.

So a little looking at RFCs and we see that RFC 2030 is very applicable, and gives us all the info we need about the protocol.

A little more looking with Google found a public server domain name from NTP.org that actually rotates through public NTP servers, so we don't have to worry about one being up or not.

Armed with nothing but the second two links I wrote a little code.  This could be far more robust, with fractional seconds. mode, stratum, precision info and all that, but I just wanted to get a reasonable time - so to the second is all I was after.

public DateTime GetNTPTime()
{
   // 0x1B == 0b11011 == NTP version 3, client - see RFC 2030
   byte[] ntpPacket = new byte[] { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

   IPAddress[] addressList = Dns.GetHostEntry("pool.ntp.org").AddressList;

   if (addressList.Length == 0)
   {
      // error
      return DateTime.MinValue;
   }

   IPEndPoint ep = new IPEndPoint(addressList[0], 123);
   UdpClient client = new UdpClient();
   client.Connect(ep);
   client.Send(ntpPacket, ntpPacket.Length);
   byte[] data = client.Receive(ref ep);

   // receive date data is at offset 32
   // Data is 64 bits - first 32 is seconds - we'll toss the fraction of a second
   // it is not in an endian order, so we must rearrange
   byte[] endianSeconds = new byte[4];
   endianSeconds[0] = (byte)(data[32 + 3] & (byte)0x7F); // turn off MSB (some servers set it)
   endianSeconds[1] = data[32 + 2];
   endianSeconds[2] = data[32 + 1];
   endianSeconds[3] = data[32 + 0];
   uint seconds = BitConverter.ToUInt32(endianSeconds, 0);

   return (new DateTime(1900, 1, 1)).AddSeconds(seconds);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值