English 中文(简体)
如何写入 NTP 客户端? [已关闭]
原标题:How to write a NTP client? [closed]
  • 时间:2012-05-25 15:51:03
  •  标签:
  • c
  • ntp
Closed. This question needs details or clarity. It is not currently accepting answers.

想要改进这个问题吗? 添加细节,并通过

Closed 9 years ago.

I m looking for an code example of NTP client write in C. I found this: Fixed some things on code,and it s able to compile. But after "sending data.." it don t nothing. I have no idea how to fix this. Where is problem into code or server? Thanks in advance.

/*
 * 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>

void ntpdate();

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

void ntpdate() {
char    *hostname="tick.usno.navy.mil";
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
int 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);
if(s) {
    perror("asd");
    printf("socket=%d
",s);
}
//
//#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
",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..
");
i=sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));

// get the data back
i=recv(s,buf,sizeof(buf),0);
printf("recvfr: %d
",i);
//perror("recvfr:");

//We get 12 long words back in Network order
/*
for(i=0;i<12;i++)
    printf("%d	%-8x
",i,ntohl(buf[i]));
*/

/*
 * 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
//printf("tmit=%d
",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
",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));
i=time(0);
//printf("%d-%d=%d
",i,tmit,i-tmit);
printf("System time is %d seconds off
",i-tmit);
}
最佳回答

无法确定 sendto () 是否屏蔽 。

要测试此测试, 您可能想要添加

printf("receiving data..
");

在呼叫recv() 之前。


此外, recv () 呼叫也可以被阻断 。

它正在等待 size of(buf) bytes, 也就是 1024* size( long)

我们从来源的评论中了解到,预计会有12个长的单词,所以你不妨考虑通过将调用 recv () 调用 类似 调用 来告诉 :

i = recv(s, buf, 12*sizeof(buf[0]), 0);

尽管如此,我仍强烈建议对系统电话添加错误检查,例如 sendo () recv () 。 要为这两个电话添加错误检查, 请测试它们返回到 -1 的值, 如果是的话, 则做一些错误处理 。

对于其他系统调用其他值可能表示错误。 详情请参见 < code> man & lt; metethod name>

问题回答

这是一套运作良好的代码。 (完全不起作用:时间戳错误, 由我制作的这个页面上的阅读和机器人邮报)。

感谢大家的分享。

 /* 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>

void ntpdate();

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

void ntpdate() {
char *hostname="163.117.202.33";
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
int 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
",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..
");
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	%-8x
",i,ntohl(buf[i]));
*/

/*
 * 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
//printf("tmit=%d
",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
",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));
i=time(0);
//printf("%d-%d=%d
",i,tmit,i-tmit);
printf("System time is %d seconds off
",i-tmit);
}

在此输出 :

$ ./sntp_client 
socket: Success
sending data..
sendto: Success
recvfr:: Success
Time: Sun Sep 26 16:00:32 4213
System time is -702316565 seconds off

Here is the code that is modified by me and compiles and executes too.
It is tested on server 2003, VS 2008. This is windows equivalent code for the Unix one u have supplied

#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 <winsock2.h>
#include <ws2tcpip.h>
#include <tchar.h>

#pragma comment(lib, "Ws2_32.lib")

void ntpdate();

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

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


//=====================================================================================
//THIS IS WHAT IS MISSING MAJORILY  
//=====================================================================================
        //Initialise the winsock stack
        WSADATA wsaData;
        BYTE wsMajorVersion = 1;
        BYTE wsMinorVersion = 1;
        WORD wVersionRequested = MAKEWORD(wsMinorVersion, wsMajorVersion);   
        if (WSAStartup(wVersionRequested, &wsaData) != 0) 
        {
            _tprintf(_T("Failed to load winsock stack
"));
            WSACleanup();
            return;
        }
        if (LOBYTE(wsaData.wVersion) != wsMajorVersion || HIBYTE(wsaData.wVersion) != wsMinorVersion)
        {
            _tprintf(_T("Winsock stack does not support version which this program requires
"));
            WSACleanup();
            return;
        }
//=====================================================================================



//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");
int err = GetLastError();
s=socket(PF_INET, SOCK_DGRAM, proto->p_proto);
if(s) {
    perror("asd");
    printf("socket=%d
",s);
}
//
//#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
",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..
");
i=sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));

int iResult = -1;
    // Receive until the peer closes the connection
    //do {

        iResult = recv(s, buf, 1024, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d
", iResult);
        else if ( iResult == 0 )
            printf("Connection closed
");
        else
            printf("recv failed: %d
", WSAGetLastError());

    //} while( iResult > 0 );

/*
 * 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
//printf("tmit=%d
",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
",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));
i=time(0);
//printf("%d-%d=%d
",i,tmit,i-tmit);
printf("System time is %d seconds off
",i-tmit);
}

您应该使用 : recvfrom () 函数来自 POSIX libc 任何 POSIX 兼容系统中的 POSIX 兼容系统, 作为 Unix 类似 。 或包容性的 Windows 。 它支持某些基本的 POSIX 函数 。

阅读使用 UDP 插座的手册, 而不是针对连接。 它们有些特殊 。

have a nice day. and hope my post helps you.

欢呼;

abel. 贝利.

你有一个完整的NTP客户 我昨天根据你的代码编码了

gracias ;)

所以,你必须改变一些功能 才能让它在Linux和 uncompment下工作,是不是?

 /* 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/
 *
 * ported to android 4.3 on mar/nov/5 - 2013 by abel.
 * the same day ported to a library for agpsd layer.
 */
/*
#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 <utils/SystemClock.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <sys/time.h>
#define NTP_MODE_CLIENT 3
#define NTP_VERSION 3
#define TRANSMIT_TIME_OFFSET 40
#define REFERENCE_TIME_OFFSET 16
#define ORIGINATE_TIME_OFFSET 24
#define RECEIVE_TIME_OFFSET 32
#define OFFSET_1900_TO_1970 ((uint64_t)((365 * 70) + 17) * 24 * 60 * 60)
*/
void ntpdate(uint64_t *cachedTime, uint64_t *cachedTimeRef, uint64_t *cacheCertainty);
/*
int main() {
    uint64_t cachedTime, cachedTimeRef, cacheCertainty;
    ntpdate(&cachedTime, &cachedTimeRef, &cacheCertainty);
    printf ("%lld
, %lld
, %lld
", cachedTime, cachedTimeRef, cacheCertainty);
    return 0;
}
*/
double random2 () {
    srandom(time(NULL));
    return random();
}

uint64_t currentTimeMillis(/*long int seconds, long int miliseconds*/) {
    struct timeval te; 
    gettimeofday(&te, NULL); // get current time
    uint64_t millis = (uint64_t) te.tv_sec * 1000 + floor(te.tv_usec / 1000); // caculate milliseconds
//  printf ("millis: %llu
", millis);
    return millis;
}

uint32_t read32(char* buffer, int offset) {
    char b0 = buffer[offset];
    char b1 = buffer[offset+1];
    char b2 = buffer[offset+2];
    char b3 = buffer[offset+3];

    // convert signed bytes to unsigned values
    uint32_t i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
    uint32_t i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
    uint32_t i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
    uint32_t i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);

    uint32_t v = (i0 << 24) + (i1 << 16) + (i2 << 8) + i3;
    return v;
}

uint64_t readTimeStamp(char *buffer, int offset) {
    uint32_t seconds  = read32(buffer, offset);
    uint32_t fraction = read32(buffer, offset + 4);
    uint64_t v = ((int64_t)seconds - OFFSET_1900_TO_1970) * 1000 + (int64_t) fraction * 1000 / (int64_t) 0x100000000;
//  printf ("%llu
", v);
    return v;
}


void writeTimeStamp(char* buffer, int offset, long long int time) {
    uint64_t seconds = floor (time / 1000);
    uint64_t milliseconds = time - (uint64_t) seconds * 1000;
    seconds += OFFSET_1900_TO_1970;

    // write seconds in big endian format
    buffer[offset++] = (char)(seconds >> 24);
    buffer[offset++] = (char)(seconds >> 16);
    buffer[offset++] = (char)(seconds >> 8);
    buffer[offset++] = (char)(seconds >> 0);

    uint64_t fraction = round ((uint64_t)milliseconds * 0x100000000 / 1000);
    // write fraction in big endian format
    buffer[offset++] = (char)(fraction >> 24);
    buffer[offset++] = (char)(fraction >> 16);
    buffer[offset++] = (char)(fraction >> 8);
    // low order bits should be random data
    buffer[offset++] = (char)(random2() * 255.0);
}

void ntpdate(uint64_t *cachedTime, uint64_t *cachedTimeRef, uint64_t *cacheCertainty) {
    char hostname[]="81.184.154.182";
    int portno=123;     //NTP is port 123
    int maxlen=48;        //check our buffers
    int i;          // misc var i
    uint64_t requestTime = currentTimeMillis();
    uint64_t requestTicks = android::elapsedRealtime();
    char msg[48];
    memset (msg,0,sizeof(msg));
    msg[0]= NTP_MODE_CLIENT | (NTP_VERSION << 3);
    writeTimeStamp(msg, TRANSMIT_TIME_OFFSET, requestTime);
    char  buf[maxlen]; // the buffer we get back
    struct sockaddr_in server_addr;
    int s;  // socket
    time_t tmit;   // the time -- This is a time_t sort of

    s=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    memset( &server_addr, 0, sizeof( server_addr ));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(hostname);
    server_addr.sin_port=htons(portno);

    i=sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
    struct sockaddr saddr;
    socklen_t saddr_l = sizeof (saddr);
    i=recvfrom(s,buf,sizeof(buf),0,&saddr,&saddr_l);

    uint64_t responseTicks = android::elapsedRealtime();
    uint64_t responseTime = requestTime + (responseTicks - requestTicks);
    uint64_t originateTime = readTimeStamp(buf, ORIGINATE_TIME_OFFSET);
    uint64_t receiveTime = readTimeStamp(buf, RECEIVE_TIME_OFFSET);
    uint64_t transmitTime = readTimeStamp(buf, TRANSMIT_TIME_OFFSET);
    uint64_t roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
    int32_t clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2;
    //printf ("%lld + %lld = %ld %ld
", (receiveTime - originateTime), (transmitTime - responseTime), (receiveTime - originateTime + transmitTime - responseTime)/2, clockOffset);
    uint64_t mNtpTime = responseTime + clockOffset;
    uint64_t mNtpTimeReference = responseTicks;
    uint64_t mRoundTripTime = roundTripTime;
    uint64_t mCachedNtpTime = mNtpTime;
    uint64_t mCachedNtpElapsedRealtime = mNtpTimeReference;
    uint64_t mCachedNtpCertainty = mRoundTripTime / 2;
    *cachedTime     = mCachedNtpTime;
    *cachedTimeRef  = mNtpTimeReference;
    *cacheCertainty = mCachedNtpCertainty;

//  uint64_t now = mNtpTime + android::elapsedRealtime() - mNtpTimeReference;
/*
    printf ("%lld
", now);
    i=currentTimeMillis();
    printf("System time is %lu miliseconds off
",i-now);
*/
}




相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...