如何写一个NTP客户端? [英] How to write a NTP client?

查看:199
本文介绍了如何写一个NTP客户端?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在寻找NTP客户端写的C.一个code例子,我发现
修正了code一些东西,它能够编译。但发送数据..后,不要什么。我不知道如何解决这一问题。哪里是问题转化为code或服务器?先谢谢了。

  / *
 *此code将查询NTP服务器的本地时间和显示
 *它。它旨在展示如何使用NTP服务器作为时间
 *源一个简单的网络连接的设备。
 *这是C版本。还原最初是在Perl
 *
 *为了更好的时钟管理看在官方NTP信息:
 * http://www.eecis.udel.edu/~ntp/
 *
 *由Tim Hogard写(thogard@abnormal.com)
 *周四09月26日13时35分41秒EAST 2002
 *转换为C周五2月21日21时42分49秒EAST 2003
 *此code是在公共领域。
 *它可以在这里找到http://www.abnormal.com/~thogard/ntp/
 *
 * /
#包括LT&;&stdio.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&; ARPA / inet.h>
#包括LT&;&netdb.h中GT;
#包括LT&;&time.h中GT;
#包括LT&;&string.h中GT;无效的ntpdate();诠释主(){
    的ntpdate();
    返回0;
}无效的ntpdate(){
字符*主机名=tick.usno.navy.mil;
INT PORTNO = 123; // NTP是123端口
INT MAXLEN = 1024; //检查我们的缓冲区
INT I; //其它变种我
unsigned char型味精[48] = {} 010,0,0,0,0,0,0,0,0; //我们发送数据包
无符号长BUF [MAXLEN] //缓冲区我们回来
// struct in_addr,这个IPADDR; //
结构protoent *原型; //
结构SOCKADDR_IN SERVER_ADDR;
int类型; //插座
INT tmit; //时间 - 这是一个time_t的排序//使用Socket;
//
//#我们使用系统调用来打开一个UDP套接字
//套接字(socket,PF_INET,SOCK_DGRAM,getprotobyname(UDP))或死插座:$!;
原= getprotobyname(UDP);
S =插座(PF_INET,SOCK_DGRAM,原型> p_proto);
如果(多个){
    PERROR(ASD);
    的printf(插座=%d个\\ N,S);
}
//
//#如果需要转换成主机名ip地址
// $ IPADDR = INET_ATON($主机名);
memset的(安培; SERVER_ADDR,0,sizeof的(SERVER_ADDR));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(主机名);
// ARGV [1]);
// I = INET_ATON(主机名,和放大器; server_addr.sin_addr);
server_addr.sin_port = htons(PORTNO);
//输出(IPADDR(十六进制):%X \\ n,server_addr.sin_addr);/ *
 *建立一个消息。我们的信息是,除了一个在全部为零
 *协议版本字段
 *味精[]以二进制为00 001 000 00000000
 *它应该是一个总的长48个字节
* ///发送数据
的printf(发送数据.. \\ n);
I = SENDTO(S,味精,sizeof的(MSG),0,(结构sockaddr *)及SERVER_ADDR,sizeof的(SERVER_ADDR));//取回数据
I = recv的(S,buf中,的sizeof(BUF),0);
的printf(recvfr数:%d \\ n,I);
// PERROR(recvfr:);//我们得到12长的背单词在网络秩序
/ *
对于(i = 0; I< 12;我++)
    的printf(%d个\\ T%-8x \\ n,我,ntohl(BUF [I]));
* // *
 *的发射时间的高位字是第10个字,我们回去
 * tmit以秒为单位的时候不占网络延迟,
 *应该比第二方式以下,如果这是一个本地NTP服务器
 * /tmit = ntohl((time_t的)的buf [10]); //#得到传输时间
//输出(tmit =%d个\\ N,tmit);/ *
 *转换时间UNIX标准时间NTP是自0000秒数
 *在1900年1月1日Unix时间UT是自0000 UT 1月1日秒
 * 1970年已经有添加2闰秒每3年的趋势。
 *闰秒只是一个问题,本月在六月最后一秒
 *月,如果你不尝试设置时钟则可以忽略不计,但
 *这是importaint的人谁与GPS时钟源协调倍。
 * /tmit- = 2208988800U;
//输出(tmit =%d个\\ N,tmit);
/ *使用UNIX的库函数来显​​示我的本地时间(它需要照顾
 对于赤道和地方两个南北时区的问题*
 *该做的夏令时/夏令时。
 * /
//#比较系统时间
的printf(时间:%S的ctime(安培; tmit));
i为时间(0);
//的printf(%D-%D =%d个\\ N,我,tmit,I-tmit);
的printf(系统时间为%d秒掉\\ n,I-tmit);
}


解决方案

这不知道是否SENDTO()阻止。

要测试这一点,你可能会想补充

 的printf(接收数据.. \\ n);

之前调用的recv()


另外,的recv()调用可能阻塞。

这等待的sizeof(BUF)字节,这是 1024 * sizeof的(长)

从源我们了解到,12长的话是预期,因此可以考虑告诉意见的recv()通过改变调用的recv()像这样:

  I =的recv(S,BUF,12 * sizeof的(BUF [0]),0);


尽管这一切我强烈建议添加错误检查系统调用,如仙道()的recv()也是。要为这两个这样做,测试他们返回是小于0的值,并做一些错误处理如果是的话。

对于其他系统调用其它值可能表示一个错误。参见男人<方法名称> 详情

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 (thogard@abnormal.com)
 * 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\n",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\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));

// get the data back
i=recv(s,buf,sizeof(buf),0);
printf("recvfr: %d\n",i);
//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]));
*/

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

解决方案

It not sure whether sendto() is blocking.

To test this you might like to add

printf("receiving data..\n");

prior to the call to recv().


Also the recv() call could block.

It awaits sizeof(buf) bytes, which is 1024* sizeof(long).

From the comments in the source we learn that 12 long words are expected, so you might consider telling recv() this by changing the call to recv() like so:

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


Despite all this I'd strongly recommend to add error checking on system calls, like sendo() and recv() also are. To do so for these two, test the value they return to be less then 0, and do some error handling if so.

For other system call other values might indicate an error. See man <method name> for details.

这篇关于如何写一个NTP客户端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆