C#에서 인터넷 타임 서버(NTP)의 현재 시간을 가져오는 로직 구현 방법(소스 설명)


프로그램을 개발할 때 현재 시간을 가져와서 처리하는 로직을 의외로 많이 구현하게 됩니다.

C# 프로그램에서 현재 시간을 가져오는 로직은 간단하게 사용할 수 있는 DateTime.Now를 가장 많이 사용하게 됩니다. 
그런데 DateTime.Now를 사용했을 때 한 가지 문제점은 가져오는 현재 시간을 사용자 컴퓨터의 현재 시간을 가져온다는 것입니다.

일반적인 응용 프로그램에서는 크게 문제되지 않을 수도 있지만 만약 예약 사이트를 만들어 정해진 시간부터 예약이 가능하도록 로직을 구현한다고 했을 때 시간 체크를 DateTime.Now의 현재 시간으로 체크를 한다면 아주 큰 문제가 발생하게 됩니다.

예약하기 전 컴퓨터 시간을 임의로 변경하고 예약을 진행하면 막을 방법이 없기 때문입니다.
12시부터 예약이 가능하도록 로직을 구현했지만 실제 현재 시간이 11시임에도 컴퓨터의 시간을 12시 이후로 변경하고 예약을 하게 되면 예약이 이루어지게 됩니다. 

그래서 중요하게 시간 체크를 하는 로직에서는 SELECT 쿼리를 사용해서 데이터베이스(DB Server) 서버의 시간을 가져와서 사용하기도 하고, NTP(Network Time Protocol)를 사용한 인터넷 타임 서버에서 현재 시간을 가져와서 사용하기도 합니다.

NTP는 네트워크를 통해 컴퓨터(디바이스)간 시간 동기화에 널리 사용되는 프로토콜 입니다.
윈도우 시스템도 기본적으로 NTP 서버를 통해 현재 날짜 및 시간을 자동으로 동기화 하고 있습니다.

이번 글에서는 C#에서 인터넷 타임 서버(NTP)의 현재 시간을 가져오는 로직 구현 방법(소스 설명)에 대해 알아보겠습니다.

C#에서 NTP(Network Time Protocol)을 사용한 타임서버에서 현재시간 가져오기

– 프로그램 소스에 사용된 Time server는 time.windows.com 입니다.

– try ~ catch를 사용하여 혹시 네트워크 연결에 문제가 있거나 타임 서버에서 제대로 시간을 가져오지 못했을 때 컴퓨터의 현재 시간으로 대체하도록 로직을 구현한 예제 입니다.

C#에서 인터넷 타임 서버(NTP)의 현재 시간을 가져오는 로직 구현 방법


▼ C#으로 구현한 실제 소스 입니다.

try
{
    //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();
    }
 
    ulong intPart = (ulong)ntpData[40<< 24 | (ulong)ntpData[41<< 16 | (ulong)ntpData[42<< 8 | (ulong)ntpData[43];
    ulong fractPart = (ulong)ntpData[44<< 24 | (ulong)ntpData[45<< 16 | (ulong)ntpData[46<< 8 | (ulong)ntpData[47];
 
    var milliseconds = (intPart * 1000+ ((fractPart * 1000/ 0x100000000L);
    var networkDateTime = (new DateTime(190011)).AddMilliseconds((long)milliseconds);
 
    textNTP_DateTime.Text = networkDateTime.ToLocalTime().ToString();
}
catch
{
    MessageBox.Show(“정확한 현재 시간을 가져오지 못했습니다.” + Environment.NewLine + “임시로 컴퓨터 시간을 가져옵니다.”);
 
    textNTP_DateTime.Text = DateTime.Now.ToString();
}
 





이 글이 도움이 되었기를 바랍니다. ^-^


답글 남기기