현재시간을 네트워크로 가져오는 이유는
디바이스의 시간은 아무래도 디바이스 클럭에 의존하기
때문에.. 조금씩 틀어진다. 누적되면 더 벌어지고..
그래서 일정주기 마다 time 서버에서 시간을 가져와서 동기화 해줘야
시간이 크게 벗어나지 않는다.
그래서 이걸 표준 프로토콜로 해서 규약으로 만들어놨는데..
RFC 5905 어쩌구 저쩌구 인데..
알겠고.. udp소켓으로 123포트로 0x1B 보내면 48개의 byte 배열을 응답해줌..
이중에서 40부터 4바이트가 정수부 44부터 4바이트가 실수부랜다..
[정수,실수]는 1900-01-01 00:00:00을 기준으로 지난 시간(초)를 UTC 기준으로 나타낸다.
접속주소는 여러군데가 있는데 다음주소중에 한군데 찍어서 가면된다.
time.nist.gov
time-a.nist.gov
time-b.nist.gov
kr.pool.ntp.org
asia.pool.ntp.org
time.bora.net
time.windows.com
time.google.com
뭐.. 더있겠지만.. 이정도면 충분하지머...
C# 코드는
public static string getNowKRtime(string time_server)
{
try
{
var ntpData = new byte[48];
ntpData[0] = 0x1B;
//
var addresses = Dns.GetHostEntry(time_server).AddressList;
var ipEndPoint = new IPEndPoint(addresses[0], 123);
//
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
socket.Connect(ipEndPoint);
socket.ReceiveTimeout = 5000;
socket.Send(ntpData);
socket.Receive(ntpData);
socket.Close();
}
//40번째부터 4바이트가 초단위 UTC기준으로
//44번째부터 4바이트가 소수점단위 UTC기준으로
byte[] intside = new byte[4] { ntpData[40], ntpData[41], ntpData[42], ntpData[43] };
byte[] flotside = new byte[4] { ntpData[44], ntpData[45], ntpData[46], ntpData[47] };
//정수부 소수부
UInt32 intPart = 0;
UInt32 floatPart = 0;
//현재시스템이 리틀엔디안인지 빅엔디안인지 비트컨버터에 있음
if (BitConverter.IsLittleEndian)
{
Array.Reverse(intside);
Array.Reverse(flotside);
}
intPart = BitConverter.ToUInt32(intside, 0);
floatPart = BitConverter.ToUInt32(flotside, 0);
//소수점은 밀리세컨드 자리까지만.. 그이상이 의미가 있을까나?? 네트웍 응답시간도 있는데..
string floatPart_str = floatPart.ToString();
floatPart_str = floatPart_str.Substring(0, Math.Min(3, floatPart_str.Length));
if (floatPart_str.Length < 3) {
int repeat = 3 - floatPart_str.Length;
for (int i = 0; i < repeat; i++) {
floatPart_str += "0";
}
}
floatPart = UInt32.Parse(floatPart_str);
//Utc시간 - 1900-01-01 00:00:00 부터 경과한 시간
DateTime default_time = new DateTime(1900, 1, 1, 0, 0, 0);
default_time = default_time.AddSeconds(intPart).AddMilliseconds(floatPart);
Console.WriteLine("네트워크에서 받은 UTC-NOW 시각: " + default_time.ToString("yyyy-MM-dd HH:mm:ss.fff"));
//한국은 9시간 차이나니까 보정하면됨..
default_time = default_time.AddHours(9);
Console.WriteLine("한국시간으로 보정된 KR-NOW 시각: " + default_time.ToString("yyyy-MM-dd HH:mm:ss.fff"));
//시스템 시간으로 보정작업 어쩌구 저쩌구
//
return default_time.ToString();
} catch (Exception ex) {
Debug.WriteLine(ex.Message);
return string.Empty;
}
}
요로코롬
댓글 없음:
댓글 쓰기