전 임베디드를 해서 해당 타겟이 int64를 지원안해서 고쳐보았습니다.
원본 소스는 http://www.codeproject.com/KB/IP/csntp.aspx 이지만 모양새는 많이 다릅니다. -_-;
// sntp.cpp : 콘솔응용프로그램에대한진입점을정의합니다.
//
#include "stdafx.h"
#include <time.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
namespace sntp
{
/////////////////////////////////////////////////////////////////////////////
//===========================================================================
#if defined ( WIN32 )
# define __little_endian__ 1
#endif
#if defined ( VXWORKS )
# define __big_endian__ 1
#endif
#define __sntp_debug_print__ 1
//===========================================================================
typedef unsigned int uint32_t;
typedef unsigned short int uint16_t;
typedef unsigned char uint8_t;
typedef signed int int32_t;
typedef signed short int int16_t;
typedef signed char int8_t;
//===========================================================================
typedef struct _system_time_t
{
uint16_t year ;
uint16_t month ;
uint16_t day_of_week ;
uint16_t day ;
uint16_t hour ;
uint16_t minute ;
uint16_t second ;
uint16_t milliseconds ;
} system_time_t;
typedef struct _timestamp_t
{
uint32_t seconds ;
uint32_t seconds_fraction ;
} timestamp_t;
typedef struct _ntp_server_response_t
{
int leap_indicator;
// 0: no warning
// 1: last minute in day has 61 seconds
// 2: last minute has 59 seconds
// 3: clock not synchronized
int stratum;
// 0: unspecified or unavailable
// 1: primary reference (e.g., radio clock)
// 2-15: secondary reference (via NTP or SNTP)
// 16-255: reserved
timestamp_t originate_timestamp ; // T1: Time when the request was sent from the client to the SNTP server
timestamp_t receive_timestamp ; // T2: Time when the request was received by the server
timestamp_t transmit_timestamp ; // T3: Time when the server sent the request back to the client
timestamp_t destination_timestamp; // T4: Time when the reply was received by the client
double round_trip_delay ; // Round trip time in seconds
double local_clock_offset ; // Local clock offset relative to the server
} ntp_server_response_t;
// Ref. RFC 2030 - Simple Network Time Protocol (SNTP) Version 4 for IPv
// http://www.faqs.org/rfcs/rfc2030.html
typedef struct _ntp_packet_t
{
#if defined ( __little_endian__ )
uint8_t mode : 3 ;
uint8_t vn : 3 ;
uint8_t li : 2 ;
#else
uint8_t li : 2 ;
uint8_t vn : 3 ;
uint8_t mode : 3 ;
#endif
uint8_t stratum ;
uint8_t poll ;
uint8_t precision ;
uint32_t root_delay ;
uint32_t root_dispersion ;
uint32_t reference_identifier ;
timestamp_t reference_timestamp ;
timestamp_t originate_timestamp ;
timestamp_t receive_timestamp ;
timestamp_t transmit_timestamp ;
} ntp_packet_t;
typedef unsigned int socket_handle_t;
/////////////////////////////////////////////////////////////////////////////
//===========================================================================
#include "sntp.inl"
static const uint16_t _socket_timeout = 1000;
static const uint16_t _socket_default_port = 123;
static const int32_t _julian_1900_01_01 = 2415021;
/////////////////////////////////////////////////////////////////////////////
//===========================================================================
inline socket_handle_t socket_create (int af, int type, int protocol)
{
return (socket_handle_t)socket (af, type, protocol);
}
inline int socket_close (socket_handle_t s)
{
return closesocket (s);
}
inline int socket_connect (socket_handle_t s, const struct sockaddr* name, int namelen)
{
return connect (s, name, namelen);
}
inline int socket_recv (socket_handle_t s, char* buf, int len, int flags)
{
return recv (s, buf, len, flags);
}
inline int socket_send (socket_handle_t s, const char* buf, int len, int flags)
{
return send (s, buf, len, flags);
}
bool socket_make_address (
struct sockaddr_in* sa,
const char* address,
uint16_t port ,
uint16_t family = AF_INET)
{
memset (sa, 0, sizeof(struct sockaddr_in));
sa->sin_family = family;
sa->sin_addr.s_addr = inet_addr(address);
if (sa->sin_addr.s_addr==INADDR_NONE)
{
struct hostent* host;
host = gethostbyname(address);
if (host != 0)
{
sa->sin_addr.s_addr = ((struct in_addr*)host->h_addr)->s_addr;
}
else
{
return false;
}
}
sa->sin_port = htons((uint16_t)port);
return true;
}
//===========================================================================
void convert_gregorian_to_julian (uint16_t year, uint16_t month, uint16_t day, int32_t& julian)
{
int32_t y ;
int32_t m ;
int32_t d ;
int32_t c ;
int32_t ya;
y = (int32_t) year ;
m = (int32_t) month;
d = (int32_t) day ;
if (m > 2)
{
m = m - 3;
}
else
{
m = m + 9;
y = y - 1;
}
c = y / 100;
ya = y - 100 * c;
julian = (146097L * c) / 4 + (1461L * ya) / 4 + (153L * m + 2) / 5 + d + 1721119L;
}
void convert_julian_to_gregorian (int32_t julian, uint16_t& year, uint16_t& month, uint16_t& day)
{
int32_t j;
int32_t y;
int32_t d;
int32_t m;
j = julian - 1721119;
y = (4 * j - 1) / 146097;
j = 4 * j - 1 - 146097 * y;
d = j / 4;
j = (4 * d + 3) / 1461;
d = 4 * d + 3 - 1461 * j;
d = (d + 4) / 4;
m = (5 * d - 3) / 153;
d = 5 * d - 3 - 153 * m;
d = (d + 5) / 5;
y = 100 * y + j;
if (m < 10)
{
m = m + 3;
}
else
{
m = m - 9;
y = y + 1;
}
year = (uint16_t) y;
month = (uint16_t) m;
day = (uint16_t) d;
}
uint32_t convert_milliseconds_to_seconds_fraction (uint16_t milliseconds)
{
#if 1
// 4294967296 == 0x1 0000 0000 (2^32)
return (uint32_t) (4294967296.0 * milliseconds / 1000);
#else
return ( milliseconds<1000 )? _seconds_fraction_table[milliseconds] : _seconds_fraction_table[999];
#endif
}
uint16_t convert_seconds_fraction_to_milliseconds (uint32_t seconds_fraction)
{
#if 1
static const double ratio = (((double)1000.0)/4294967296.0);
double milliseconds = ((double)seconds_fraction) * ratio;
#else
static const double ratio = (((double)1000.0)/0xFFFFFFFF);
double milliseconds = ((double)seconds_fraction) * ratio + 0.5;
#endif
return (uint16_t)(milliseconds);
}
void make_timestamp (
timestamp_t& timestamp ,
uint16_t year ,
uint16_t month = 1 ,
uint16_t day = 1 ,
uint16_t hour = 0 ,
uint16_t minute = 0 ,
uint16_t second = 0 ,
uint16_t milliseconds = 0 )
{
int32_t julian;
convert_gregorian_to_julian (year,month,day, julian);
julian = julian - _julian_1900_01_01;
timestamp.seconds = (julian*24*60*60) + (hour*60*60) + (minute*60) + second;
timestamp.seconds_fraction = convert_milliseconds_to_seconds_fraction (milliseconds);
}
//===========================================================================
void get_current_timestamp (timestamp_t& timestamp)
{
#if 0
static const uint32_t from_1900_to_1970 = 86400U * (365U*70U + 17U);
uint32_t t;
t = (uint32_t)time (0); // time(): 1970-01-01 based
t+= from_1900_to_1970;
timestamp.seconds = t;
timestamp.seconds_fraction = 0;
#else
SYSTEMTIME st;
GetSystemTime (&st);
make_timestamp (timestamp,
st.wYear ,
st.wMonth ,
//st.wDayOfWeek ,
st.wDay ,
st.wHour ,
st.wMinute ,
st.wSecond ,
st.wMilliseconds);
#endif
}
//===========================================================================
void convert_timestamp_to_system_time (const timestamp_t& timestamp, system_time_t& system_time)
{
uint32_t julian;
system_time.hour = (timestamp.seconds/3600)%24;
system_time.minute = (timestamp.seconds/60 )%60;
system_time.second = (timestamp.seconds )%60;
system_time.milliseconds = convert_seconds_fraction_to_milliseconds (timestamp.seconds_fraction);
julian = timestamp.seconds/86400 + _julian_1900_01_01;
convert_julian_to_gregorian (julian, system_time.year, system_time.month, system_time.day);
system_time.day_of_week = ((julian+1) % 7);
}
void print_timestamp (const timestamp_t& timestamp)
{
system_time_t system_time;
const char* day_of_week_string[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
convert_timestamp_to_system_time (timestamp, system_time);
printf ("%4d-%02d-%02d(%s) %02d:%02d:%02d.%03d \r\n",
system_time.year ,
system_time.month ,
system_time.day ,
day_of_week_string[system_time.day_of_week],
system_time.hour ,
system_time.minute ,
system_time.second ,
system_time.milliseconds);
}
//===========================================================================
bool client_request (
ntp_server_response_t& response ,
struct sockaddr_in* server_address ,
uint32_t milisec_timeout = _socket_timeout)
{
socket_handle_t socket_handle;
struct timeval timeout;
fd_set fds;
int result;
socket_handle = socket_create (AF_INET, SOCK_DGRAM, 0);
if (socket_handle < 0)
{
return false;
}
result = socket_connect (socket_handle, (struct sockaddr*) server_address, sizeof(struct sockaddr_in));
if (result < 0)
{
socket_close(socket_handle);
return false;
}
// ntp packet
ntp_packet_t ntp_packet;
timestamp_t timestamp ;
memset(&ntp_packet, 0, sizeof(ntp_packet));
ntp_packet.vn = 4;
ntp_packet.mode = 3;
ntp_packet.li = 0;
get_current_timestamp (timestamp);
ntp_packet.transmit_timestamp.seconds = htonl(timestamp.seconds );
ntp_packet.transmit_timestamp.seconds_fraction = htonl(timestamp.seconds_fraction);
// T1
response.originate_timestamp.seconds = timestamp.seconds ;
response.originate_timestamp.seconds_fraction = timestamp.seconds_fraction;
result = socket_send (socket_handle, (char*)&ntp_packet, sizeof(ntp_packet), 0);
if ( result != sizeof(ntp_packet) )
{
socket_close (socket_handle);
return false;
}
FD_ZERO (&fds);
FD_SET (socket_handle, &fds);
timeout.tv_sec = milisec_timeout / 1000;
timeout.tv_usec = (milisec_timeout % 1000) * 1000;
result = select (socket_handle+1, &fds, NULL, NULL, &timeout);
if ( result == 0 || result == -1 )
{
socket_close(socket_handle);
return false;
}
// T4
get_current_timestamp (timestamp);
response.destination_timestamp.seconds = timestamp.seconds ;
response.destination_timestamp.seconds_fraction = timestamp.seconds_fraction;
result = socket_recv (socket_handle, (char*)&ntp_packet, sizeof(ntp_packet), 0);
if ( result != sizeof(ntp_packet) )
{
socket_close(socket_handle);
return false;
}
socket_close (socket_handle);
// T2/3
response.receive_timestamp.seconds = ntohl(ntp_packet.receive_timestamp.seconds );
response.receive_timestamp.seconds_fraction = ntohl(ntp_packet.receive_timestamp.seconds_fraction );
response.transmit_timestamp.seconds = ntohl(ntp_packet.transmit_timestamp.seconds );
response.transmit_timestamp.seconds_fraction = ntohl(ntp_packet.transmit_timestamp.seconds_fraction);
//-----------------------------------------------------------------------
// Timestamp Name ID When Generated
//-----------------------------------------------------------------------
// Originate Timestamp T1 time request sent by client
// Receive Timestamp T2 time request received by server
// Transmit Timestamp T3 time reply sent by server
// Destination Timestamp T4 time reply received by client
/*
The roundtrip delay(d)
d = (T4 - T1) - (T2 - T3)
local clock offset t are defined as
t = ((T2 - T1) + (T3 - T4)) / 2.
*/
static const uint32_t NTP_DIFF = 2208988800U; // 1970-01-01
static const double NTP_SCALE = 2.3283064365e-10; // 2^-32
double t1,t2,t3,t4;
t1=response.originate_timestamp .seconds-NTP_DIFF + response.originate_timestamp .seconds_fraction * NTP_SCALE;
t2=response.receive_timestamp .seconds-NTP_DIFF + response.receive_timestamp .seconds_fraction * NTP_SCALE;
t3=response.transmit_timestamp .seconds-NTP_DIFF + response.transmit_timestamp .seconds_fraction * NTP_SCALE;
t4=response.destination_timestamp.seconds-NTP_DIFF + response.destination_timestamp.seconds_fraction * NTP_SCALE;
response.round_trip_delay = (t4 - t1) - (t2 - t3);
response.local_clock_offset = ((t2 - t1) + (t3 - t4)) * 0.5;
//-----------------------------------------------------------------------
response.stratum = ntp_packet.stratum;
response.leap_indicator = ntp_packet.li;
#if __sntp_debug_print__
printf ("# sntp_debug \r\n");
printf (" li = %d \r\n", ntp_packet.li );
printf (" vn = %d \r\n", ntp_packet.vn );
printf (" mode = %d \r\n", ntp_packet.mode );
printf (" stratum = 0x%02x \r\n", ntp_packet.stratum );
printf (" poll = 0x%02x \r\n", ntp_packet.poll );
printf (" precision = 0x%02x \r\n", ntp_packet.precision );
printf (" root_delay = 0x%08x \r\n", ntp_packet.root_delay );
printf (" root_dispersion = 0x%08x \r\n", ntp_packet.root_dispersion );
printf (" reference_identifier= 0x%08x \r\n", ntp_packet.reference_identifier );
printf (" reference_timestamp = ");
timestamp.seconds =ntohl(ntp_packet.reference_timestamp.seconds );
timestamp.seconds_fraction=ntohl(ntp_packet.reference_timestamp.seconds_fraction);
print_timestamp (timestamp);
printf (" originate_timestamp = ");
timestamp.seconds =ntohl(ntp_packet.originate_timestamp.seconds );
timestamp.seconds_fraction=ntohl(ntp_packet.originate_timestamp.seconds_fraction);
print_timestamp (timestamp);
printf (" receive_timestamp = ");
timestamp.seconds =ntohl(ntp_packet.receive_timestamp .seconds );
timestamp.seconds_fraction=ntohl(ntp_packet.receive_timestamp .seconds_fraction);
print_timestamp (timestamp);
printf (" transmit_timestamp = ");
timestamp.seconds =ntohl(ntp_packet.transmit_timestamp .seconds );
timestamp.seconds_fraction=ntohl(ntp_packet.transmit_timestamp .seconds_fraction);
print_timestamp (timestamp);
printf ("\r\n");
printf (" round_trip_delay = %f \r\n", response.round_trip_delay );
printf (" local_clock_offset = %f \r\n", response.local_clock_offset);
#endif
return true;
}
bool get_time (timestamp_t& adjusted_time, const char* address, uint16_t port = _socket_default_port)
{
ntp_server_response_t response;
struct sockaddr_in sa;
if (false==socket_make_address (&sa, address, port))
return false;
if (false==client_request(response, &sa))
return false;
uint32_t offset_second ;
uint32_t offset_milliseconds ;
uint32_t current_milliseconds;
uint32_t current_second ;
timestamp_t current_timestamp ;
double offset;
bool offset_negative;
offset = (0>response.local_clock_offset)? -1.0*response.local_clock_offset : response.local_clock_offset;
offset_negative = (0>response.local_clock_offset)? true : false;
offset_second = (uint32_t)( offset );
offset_milliseconds = (uint32_t)((offset-offset_second)*1000);
get_current_timestamp (current_timestamp);
current_second = current_timestamp.seconds;
current_milliseconds = convert_seconds_fraction_to_milliseconds (current_timestamp.seconds_fraction);
if (offset_negative)
{
if (current_milliseconds<offset_milliseconds)
{
current_milliseconds = 1000+current_milliseconds-offset_milliseconds;
current_second = current_second-offset_second - 1;
}
else
{
current_milliseconds = current_milliseconds-offset_milliseconds;
current_second = current_second-offset_second;
}
}
else
{
current_milliseconds+=offset_milliseconds;
current_second = current_second+offset_second + (current_milliseconds/1000);
current_milliseconds = current_milliseconds%1000;
}
current_timestamp.seconds = current_second;
current_timestamp.seconds_fraction = convert_milliseconds_to_seconds_fraction (current_milliseconds);
memcpy (&adjusted_time, ¤t_timestamp, sizeof(adjusted_time));
return true;
}
//===========================================================================
} // end of "namespace sntp { "
/////////////////////////////////////////////////////////////////////////////
//===========================================================================
void TRACE (const TCHAR* lpFormatStr, ...)
{
TCHAR szBuffer[256];
va_list args;
va_start (args, lpFormatStr);
#pragma warning( push )
#pragma warning( disable : 4996 )
_vsntprintf (szBuffer, 256, lpFormatStr, args);
#pragma warning( pop )
va_end (args);
OutputDebugStringA (szBuffer);
printf (szBuffer);
}
class adjust_settime_priviledge
{
public:
HANDLE _token_handle ;
TOKEN_PRIVILEGES _token_privileges;
BOOL _taken_priviledge;
public:
adjust_settime_priviledge ():
_token_handle (0),
_taken_priviledge(FALSE)
{
ZeroMemory(&_token_privileges, sizeof(TOKEN_PRIVILEGES));
}
~adjust_settime_priviledge ()
{
revert_settime_priviledge ();
}
public:
BOOL enable_settime_priviledge (void)
{
BOOL opentoken;
BOOL success ;
_taken_priviledge = FALSE;
opentoken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &_token_handle);
if (!opentoken)
{
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
//Must be running on 95 or 98 not NT. In that case just ignore the error
SetLastError(ERROR_SUCCESS);
return TRUE;
}
TRACE(_T("Failed to get Adjust priviledge token\n"));
return FALSE;
}
ZeroMemory(&_token_privileges, sizeof(TOKEN_PRIVILEGES));
if (!LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &_token_privileges.Privileges[0].Luid))
{
TRACE(_T("Failed in callup to lookup priviledge\n"));
return FALSE;
}
_token_privileges.PrivilegeCount = 1;
_token_privileges.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
_taken_priviledge = TRUE;
success = AdjustTokenPrivileges(_token_handle, FALSE, &_token_privileges, 0, NULL, 0);
if (!success)
{
TRACE(_T("Failed to adjust SetTime priviledge\n"));
}
return success;
}
void revert_settime_priviledge (void)
{
if (_taken_priviledge)
{
_token_privileges.Privileges[0].Attributes &= (~SE_PRIVILEGE_ENABLED);
if (!AdjustTokenPrivileges(_token_handle, FALSE, &_token_privileges, 0, NULL, 0))
{
TRACE(_T("Failed to reset SetTime priviledge\n"));
}
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsadata;
sntp::timestamp_t adjusted_time;
WSAStartup(MAKEWORD(2,2), &wsadata);
// if (true==sntp::get_time (adjusted_time, "time.windows.com"))
if (true==sntp::get_time (adjusted_time, "time.nist.gov"))
// if (true==sntp::get_time (adjusted_time, "time.nuri.net"))
{
adjust_settime_priviledge asp;
if (TRUE==asp.enable_settime_priviledge ())
{
sntp::system_time_t st;
convert_timestamp_to_system_time (adjusted_time, st);
SetSystemTime((SYSTEMTIME*)&st);
printf ("\r\n# adjusted_time: ");
print_timestamp (adjusted_time);
}
}
WSACleanup();
return 0;
}
결과