Yang saya butuhkan hanyalah cara untuk menanyakan Server NTP menggunakan C # untuk mendapatkan Tanggal Waktu Server NTP dikembalikan sebagai a string
atau sebagai DateTime
.
Bagaimana ini mungkin dalam bentuk yang paling sederhana?
Karena jawaban lama yang diterima dihapus (Itu adalah tautan ke hasil pencarian kode Google yang tidak ada lagi), saya pikir saya bisa menjawab pertanyaan ini untuk referensi di masa mendatang:
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));
}
Catatan: Anda harus menambahkan ruang nama berikut
using System.Net;
using System.Net.Sockets;
DateTime.ToLocalTime()
socket.Receive(ntpData);
) ia akan melempar pengecualian:An existing connection was forcibly closed by the remote host
. Tapi semua baik-baik saja Jika saya menggunakan baris perintahnet time
untuk mendapatkan waktu.Ini adalah versi fungsi yang dioptimalkan yang menghilangkan ketergantungan pada fungsi BitConverter dan membuatnya kompatibel dengan NETMF (.NET Micro Framework)
sumber
socket.ReceiveTimeout = 3000;
... ini mencegahnya macet jika ada masalah jaringan. Nilainya dalam milidetik.NET Micro Framework Toolkit ditemukan di CodePlex memiliki
NTPClient
. Saya sendiri belum pernah menggunakannya, tapi kelihatannya bagus.Ada juga contoh lain yang terletak di sini .
sumber
Saya tahu topiknya sudah cukup lama, tetapi alat seperti itu selalu berguna. Saya telah menggunakan sumber daya di atas dan membuat versi NtpClient yang memungkinkan asynchronous mendapatkan waktu yang akurat, bukan berdasarkan peristiwa.
Pemakaian:
sumber
Versi yang dimodifikasi untuk mengimbangi waktu jaringan dan menghitung dengan DateTime-Ticks (lebih tepat daripada milidetik)
sumber
http://www.codeproject.com/Articles/237501/Windows-Phone-NTP-Client akan bekerja dengan baik untuk Windows Phone.
Menambahkan kode yang relevan
Penggunaan:
sumber
Socket
adalah aIDisposable
. Anda harus mendesain kelas Anda dengan pemikiran tersebut dan memberikan cara untuk melepaskan soket baik pada penggunaan normal dan setiap kali pengecualian dimunculkan. Kode ini memang menyebabkan kebocoran memori