2013-04-09 36 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)); 
} 
相關問題