2013-04-09 56 views
2

我需要开发一个从NTP服务器获取当前时间的应用程序,但在Windows 8 Store App中找不到任何示例。如果我尝试使用正常的C#类,它不起作用。有谁知道如何解决这个问题?在Windows 8 App中使用C#从NTP服务器获取时间应用

+0

“它不起作用”对问题的描述过于模糊。请编辑您的问题以更具体。 – 2013-04-09 20:17:23

+0

可能重复的[如何使用C#查询NTP服务器?](http://stackoverflow.com/questions/1193955/how-to-query-an-ntp-server-using-c) – Nasreddine 2015-06-30 15:05:26

回答

1

我认为这是你想要的。

using System.Net; 
using System.Net.Http; 
using System.Text.RegularExpressions; 
using System.Threading.Tasks; 

private async Task<DateTime?> GetNistTime() 
{ 
    DateTime? dateTime = null; 
    HttpClient httpClient = new HttpClient(); 
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://nist.time.gov/timezone.cgi?UTC/s/0")); 
    HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); 
    string text = await httpResponseMessage.Content.ReadAsStringAsync(); 
    if (httpResponseMessage.StatusCode == HttpStatusCode.OK) 
    { 
     string html = await httpResponseMessage.Content.ReadAsStringAsync(); 
     string time = Regex.Match(html, @">\d+:\d+:\d+<").Value; //HH:mm:ss format 
     string date = Regex.Match(html, @">\w+,\s\w+\s\d+,\s\d+<").Value; //dddd, MMMM dd, yyyy 
     dateTime = DateTime.Parse((date + " " + time).Replace(">", "").Replace("<", "")); 
    } 
    return dateTime; 
} 
+0

'HttpClient'有一个'GetStringAsync' - 不需要'HttpRequestMessage' /'HttpResponseMessage'开销。除此之外 - 当页面结构发生变化时,直接字符串解析在长期运行中势必会引发问题。 – 2013-05-05 20:17:18

0

您需要一个StreamSocket,然后自己实施NTP网络协议。如果您有经典Windows的现有NTP C#类,则可以改为使用代码StreamSocket

2

我强烈建议避免字符串解析出HTML页面 - 轻微的视图格式更改会破坏您的应用程序。

基于在this answer提供的示例中,这里是DatagramSocket适应得到适当DateTime对象:

DatagramSocket socket = new DatagramSocket(); 
socket.MessageReceived += socket_MessageReceived; 
await socket.ConnectAsync(new HostName("time.windows.com"), "123"); 

using (DataWriter writer = new DataWriter(socket.OutputStream)) 
{ 
    byte[] container = new byte[48]; 
    container[0] = 0x1B; 

    writer.WriteBytes(container); 
    await writer.StoreAsync(); 
} 

当接收到消息时,可以通过一个内置处理传入的字节数组在阅读器:

void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) 
{ 
    using (DataReader reader = args.GetDataReader()) 
    { 
     byte[] b = new byte[48]; 

     reader.ReadBytes(b); 

     DateTime time = GetNetworkTime(b); 
    } 
} 

GetNetworkTime是几乎相同的,如我所提到的例子中,用作为arg的一个传递的缓冲区请注意:

public static DateTime GetNetworkTime(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 
    var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds); 

    return networkDateTime; 
} 

// stackoverflow.com/a/3294698/162671 
static uint SwapEndianness(ulong x) 
{ 
    return (uint)(((x & 0x000000ff) << 24) + 
        ((x & 0x0000ff00) << 8) + 
        ((x & 0x00ff0000) >> 8) + 
        ((x & 0xff000000) >> 24)); 
} 
相关问题