윈도우 시간 동기화

프로그램을 개발하면서 윈도우의 시간동기화가 필수적으로 필요하게 되었습니다. 당연히 윈도우가 자동으로 잘 동기화를 하고 있겠지만은 그렇지 않은 경우에는 강제로 동기화를 해야 하는데, 컴퓨터가 그냥 자동으로 작업을 할 경우에 시간에 예약이 있을 경우에 시간이 동기화가 되지 않으면은 작업이 늦어지기에 한번씩 동기화를 해줘야 합니다.

/// <summary>
/// Gets the current DateTime from time-a.nist.gov.
/// </summary>
/// <returns>A DateTime containing the current time.</returns>
public static DateTime GetNetworkTime()
{
    return GetNetworkTime("time.windows.com"); // time-a.nist.gov
}
 
/// <summary>
/// Gets the current DateTime from <paramref name="ntpServer"/>.
/// </summary>
/// <param name="ntpServer">The hostname of the NTP server.</param>
/// <returns>A DateTime containing the current time.</returns>
public static DateTime GetNetworkTime(string ntpServer)
{
    IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;
 
    if (address == null || address.Length == 0)
        throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer");
 
    IPEndPoint ep = new IPEndPoint(address[0], 123);
 
    return GetNetworkTime(ep);
}
 
/// <summary>
/// Gets the current DateTime form <paramref name="ep"/> IPEndPoint.
/// </summary>
/// <param name="ep">The IPEndPoint to connect to.</param>
/// <returns>A DateTime containing the current time.</returns>
public static DateTime GetNetworkTime(IPEndPoint ep)
{
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 
    s.Connect(ep);
 
    byte[] ntpData = new byte[48]; // RFC 2030 
    ntpData[0] = 0x1B;
    for (int i = 1; i < 48; i++)
        ntpData[i] = 0;
 
    s.Send(ntpData);
    s.Receive(ntpData);
 
    byte offsetTransmitTime = 40;
    ulong intpart = 0;
    ulong fractpart = 0;
 
    for (int i = 0; i <= 3; i++)
        intpart = 256 * intpart + ntpData[offsetTransmitTime + i];
 
    for (int i = 4; i <= 7; i++)
        fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];
 
    ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
    s.Close();
 
    TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
 
    DateTime dateTime = new DateTime(1900, 1, 1);
    dateTime += timeSpan;
 
    TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
    DateTime networkDateTime = (dateTime + offsetAmount);
 
    return networkDateTime.AddHours(-9);
}


[DllImport("kernel32")]
public static extern int SetSystemTime(ref SYSTEMTIME lpSystemTime);
 
 
public struct SYSTEMTIME
{
    public short wYear; //년도
    public short wMonth; //월
    public short wDayOfWeek; //요일
    public short wDay; //일
    public short wHour; //시
    public short wMinute; //분
    public short wSecond; //초
    public short wMilliseconds; //1/100초
}
 
private void setNowTime()
{
    SYSTEMTIME sTime = new SYSTEMTIME();
    sTime.wYear = Convert.ToInt16(GetNetworkTime().Year);
    sTime.wMonth = Convert.ToInt16(GetNetworkTime().Month);
    sTime.wDayOfWeek = Convert.ToInt16(GetNetworkTime().DayOfWeek);
    sTime.wDay = Convert.ToInt16(GetNetworkTime().Day);
    sTime.wHour = Convert.ToInt16(GetNetworkTime().Hour);
    sTime.wMinute = Convert.ToInt16(GetNetworkTime().Minute);
    sTime.wSecond = Convert.ToInt16(GetNetworkTime().Second);
    sTime.wMilliseconds = Convert.ToInt16(GetNetworkTime().Millisecond);
    SetSystemTime(ref sTime);
}

관리자 권한으로 실행이 되어 있다면은 프로그램이 시간 정보를 동기화 해서 현재 시간을 맞춰주게 되어 있습니다. 어느정도 시간의 여유를 두고 한번씩 실행을 해주면은 시간정보가 동기화 되어서 정확한 예약 시간에 프로그램이 실행이 되도록 될 것입니다.

이전글
다음글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다