Is there any C/C++ library to connect with a remote NTP server?

18,220

Solution 1

Would it not be a better solution to just have ntpd running on said system to ensure clock being correct instead of having your software manually issuing a sync and possibly causing issues with other applications not enjoying sudden time jumps, especially backwards.

That being said there is libntp I believe.

I'll drop in more things as Google finds them for me.

Solution 2

this works in c++ (adapted from c). it will get you UTC time from pool.ntp.br (you MUST use IP). if you manage to work out how to get DAYTIME (daylight savings - horario verao), please advise. i can get it from UFRJ pads servers, but UFRJ is unreliable, what with them being on strike half the year...

/* This code will query a ntp server for the local time and display

 * it.  it is intended to show how to use a NTP server as a time
 * source for a simple network connected device.
 * This is the C version.  The orignal was in Perl
 *
 * For better clock management see the offical NTP info at:
 * http://www.eecis.udel.edu/~ntp/
 *
 * written by Tim Hogard ([email protected])
 * Thu Sep 26 13:35:41 EAST 2002
 * Converted to C Fri Feb 21 21:42:49 EAST 2003
 * this code is in the public domain.
 * it can be found here http://www.abnormal.com/~thogard/ntp/
 *
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <string.h>
#include <iostream>

void ntpdate();

int main() {
    ntpdate();
    return 0;
}

void ntpdate() {
//char *hostname=(char *)"163.117.202.33";
//char *hostname=(char *)"pool.ntp.br";
char    *hostname=(char *)"200.20.186.76";
int portno=123;     //NTP is port 123
int maxlen=1024;        //check our buffers
int i;          // misc var i
unsigned char msg[48]={010,0,0,0,0,0,0,0,0};    // the packet we send
unsigned long  buf[maxlen]; // the buffer we get back
//struct in_addr ipaddr;        //  
struct protoent *proto;     //
struct sockaddr_in server_addr;
int s;  // socket
long tmit;   // the time -- This is a time_t sort of

//use Socket;
//
//#we use the system call to open a UDP socket
//socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!";
proto=getprotobyname("udp");
s=socket(PF_INET, SOCK_DGRAM, proto->p_proto);
perror("socket");
//
//#convert hostname to ipaddress if needed
//$ipaddr   = inet_aton($HOSTNAME);
memset( &server_addr, 0, sizeof( server_addr ));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr = inet_addr(hostname);
//argv[1] );
//i   = inet_aton(hostname,&server_addr.sin_addr);
server_addr.sin_port=htons(portno);
//printf("ipaddr (in hex): %x\n",server_addr.sin_addr);

/*
 * build a message.  Our message is all zeros except for a one in the
 * protocol version field
 * msg[] in binary is 00 001 000 00000000 
 * it should be a total of 48 bytes long
*/

// send the data
printf("sending data..\n");
i=sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
perror("sendto");
// get the data back
struct sockaddr saddr;
socklen_t saddr_l = sizeof (saddr);
i=recvfrom(s,buf,48,0,&saddr,&saddr_l);
perror("recvfr:");

//We get 12 long words back in Network order
/*
for(i=0;i<12;i++) {
    //printf("%d\t%-8x\n",i,ntohl(buf[i]));
    long tmit2=ntohl((time_t)buf[i]);
    std::cout << "Round number " << i << " time is " << ctime(&tmit2)  << std::endl;
}
*/
/*
 * The high word of transmit time is the 10th word we get back
 * tmit is the time in seconds not accounting for network delays which
 * should be way less than a second if this is a local NTP server
 */

//tmit=ntohl((time_t)buf[10]);    //# get transmit time
tmit=ntohl((time_t)buf[4]);    //# get transmit time
//printf("tmit=%d\n",tmit);

/*
 * Convert time to unix standard time NTP is number of seconds since 0000
 * UT on 1 January 1900 unix time is seconds since 0000 UT on 1 January
 * 1970 There has been a trend to add a 2 leap seconds every 3 years.
 * Leap seconds are only an issue the last second of the month in June and
 * December if you don't try to set the clock then it can be ignored but
 * this is importaint to people who coordinate times with GPS clock sources.
 */

tmit-= 2208988800U; 
//printf("tmit=%d\n",tmit);
/* use unix library function to show me the local time (it takes care
 * of timezone issues for both north and south of the equator and places
 * that do Summer time/ Daylight savings time.
 */


//#compare to system time
//printf("Time: %s",ctime(&tmit));

std::cout << "time is " << ctime(&tmit)  << std::endl;
i=time(0);
//printf("%d-%d=%d\n",i,tmit,i-tmit);
//printf("System time is %d seconds off\n",(i-tmit));
std::cout << "System time is " << (i-tmit) << " seconds off" << std::endl;
}
Share:
18,220
César Ortiz
Author by

César Ortiz

Updated on July 11, 2022

Comments

  • César Ortiz
    César Ortiz almost 2 years

    I'm making a C++ software that needs to syncronize system clock with remote NTP server. For now, I'm ussing "system" command to call the console "ntpdate" command.

    ..But I think is an ugly way to do that.

    Do you know any library that let me connect to remote NTP server? Thanks.

  • Li-aung Yip
    Li-aung Yip about 12 years
    +1 for ntpd and the phrase sudden time jumps. BACK TO THE FUTURE!
  • r_ahlskog
    r_ahlskog about 12 years
    @Li-aungYip, yep, having manually used ntpdate I have had all sorts of processes fail when files are from the future.
  • Li-aung Yip
    Li-aung Yip about 12 years
    The most fun (user visible) one I've had is that jumping the clock causes KDE's compositing window manager to freak out and die. Apparently kwm keeps track of its performance with a timestamp since the last frame was rendered, the intent being to turn off compositing if things get too slow. Jumping the clock forwards 10 seconds makes it think it's only getting 0.1 FPS and triggers kwms death. ;)
  • r_ahlskog
    r_ahlskog about 12 years
    That does sound fun and probably how it is solved, maybe need to try nagging some kwin dev about how good an idea that was. Naah they just tell me to fix it and send a patch no fun there.
  • César Ortiz
    César Ortiz about 12 years
    yes, ntpd seems to be the rigth way :). Thanks for the advice and for the funny comments.
  • hmojtaba
    hmojtaba over 6 years
    You may want to look at ntpclient code on github: github.com/lettier/ntpclient/blob/master/source/c/main.c also there is documentation related to this on: lettier.github.io/posts/…
  • F1iX
    F1iX almost 6 years
    NTPClient is an elegant alternative for Windows using the boost libraries (make sure to compile and add the paths). As discussed here, ntp.flags.mode in unsigned char msg[48]={010,0,0,0,0,0,0,0,0} and the buffer extraction position in tmit=ntohl((time_t)buf[4]); may have to be changed according to your goals.