C#通用Windows应用程序如何从internet获取时间
我在运行Windows10IoT内核的Raspberry Pi3上遇到了问题,因为系统时钟会随着时间的推移明显漂移。我决定制作一个程序,将系统时钟设置回正确的时间,设备将从互联网上获取。我已经知道如何设置系统时钟,但问题是:在Windows 10 IoT core上运行C#Universal Windows应用程序时,如何从互联网获取精确的时间 为了从x86和x64上的windows time server获取时间,我以前做过以下工作:C#通用Windows应用程序如何从internet获取时间,c#,datetime,win-universal-app,windows-10-universal,windows-10-iot-core,C#,Datetime,Win Universal App,Windows 10 Universal,Windows 10 Iot Core,我在运行Windows10IoT内核的Raspberry Pi3上遇到了问题,因为系统时钟会随着时间的推移明显漂移。我决定制作一个程序,将系统时钟设置回正确的时间,设备将从互联网上获取。我已经知道如何设置系统时钟,但问题是:在Windows 10 IoT core上运行C#Universal Windows应用程序时,如何从互联网获取精确的时间 为了从x86和x64上的windows time server获取时间,我以前做过以下工作: public static DateTime GetNet
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
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));
}
publicstaticdatetime GetNetworkTime()
{
//默认Windows时间服务器
常量字符串ntpServer=“time.windows.com”;
//NTP消息大小-摘要的16字节(RFC 2030)
var ntpData=新字节[48];
//设置Leap指示器、版本号和模式值
ntpData[0]=0x1B;//LI=0(无警告),VN=3(仅限IPv4),Mode=3(客户端模式)
var addresses=Dns.GetHostEntry(ntpServer.AddressList);
//分配给NTP的UDP端口号为123
var ipEndPoint=新的ipEndPoint(地址[0],123);
//NTP使用UDP
var套接字=新套接字(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
插座连接(ipEndPoint);
//如果NTP被阻止,则停止代码挂起
socket.ReceiveTimeout=3000;
socket.Send(ntpData);
套接字接收(ntpData);
socket.Close();
//到达“传输时间戳”字段的偏移量(回复的时间
//以64位时间戳格式为客户端退出服务器。“
常量字节serverReplyTime=40;
//得到秒的部分
ulong intPart=BitConverter.ToUInt32(ntpData,serverReplyTime);
//得到秒分数
ulong fractPart=BitConverter.ToUInt32(ntpData,serverReplyTime+4);
//从大端到小端的转换
intPart=SwapEndianness(intPart);
fractPart=SwapEndianness(fractPart);
变量毫秒=(intPart*1000)+(fractPart*1000)/0x10000000L;
//**UTC**时间
var networkDateTime=(新的DateTime(1900,1,1,0,0,0,DateTimeKind.Utc)).addmillizes((长)毫秒);
返回networkDateTime.ToLocalTime();
}
//stackoverflow.com/a/3294698/162671
静态uint SwapEndianness(ulong x)
{
返回(uint)((x&0x000000ff)8)+
((x&0xff000000)>>24));
}
但它不适用于通用windows应用程序,因为Dns和其他相关类不可使用。选项1
避免这个问题,不要使用互联网时间。相反,使用实时时钟集成电路,如
选择2
使用Windows 10通用应用程序类通过UDP进行连接。它们使用。下面是一些实现数据报套接字并从时间服务器返回响应的粗略代码
private async void ConnectToTimeServer(object sender, RoutedEventArgs e)
{
var socket = new DatagramSocket();
socket.MessageReceived += SocketMessageReceived;
await socket.ConnectAsync(new HostName("time.windows.com"), "123");
using (var dataWriter = new DataWriter(socket.OutputStream))
{
var ntpData = new byte[48];
ntpData[0] = 0x1B;
dataWriter.WriteBytes(ntpData);
await dataWriter.StoreAsync();
}
}
然后,消息接收到如下事件代码:
private void SocketMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
try
{
using (var reader = args.GetDataReader())
{
byte[] response = new byte[48];
reader.ReadBytes(response);
YourMethodToParseNetworkTime(response);
}
}
catch (Exception ex)
{
// Handle exceptions
}
}
感谢您的回答。这有助于解决问题。由于某些原因,在互联网上很难找到关于此主题的任何内容。根据我的经验,我推荐DS3231,而不是1302。我发现它更准确,漂移小得多。