最进写一个ntp客户端,获得时间服务器,好多地方都用,挺好的,协议部分网上多得是,还行,误差秒及的;
#define EPOCH_DIFF ((unsigned long) 86400 * (365 * 70 + 17))
double synctime (char *server_name)
{
int i, r, udp;
static int firstsync = 1;
char buf[61];
ssize_t len;
static time_t errstart = 0;
static struct timeval tv1, tv2, tv3, tv4, tvnew, cmpval;
struct timezone tz;
double t1, t2, t3, t4, toff, tnew;
time_t now;
struct sockaddr_in server;
struct in_addr server_addr;
struct hostent *server_hostent;
int count;
fd_set rd_fd;
fd_set wr_fd;
struct timeval time_out;
int mark;
mark = 0;
r = inet_aton (server_name, &server_addr);
if (r == 0)
{
server_hostent = gethostbyname (server_name);
if(server_hostent == NULL)
{
return 0;
}
server_addr.s_addr =
((server_hostent->h_addr_list[0][3] << 24) & 0xFF000000) |
((server_hostent->h_addr_list[0][2] << 16) & 0x00FF0000) |
((server_hostent->h_addr_list[0][1] << 8) & 0x0000FF00) |
(server_hostent->h_addr_list[0][0] & 0x000000FF);
}
server.sin_family = AF_INET;
server.sin_addr = server_addr;
server.sin_port = htons (SNTP_PORT);
udp = socket (PF_INET, SOCK_DGRAM, 0);
r = connect (udp, (struct sockaddr*) &server, sizeof (server));
if (r == -1)
{
now = time (NULL);
if (errstart == 0)
errstart = now;
r = close (udp);
return 0;
}
for (i = 0; i < 61; i++)
buf[i] = 0;
buf[0] = (0 << 6) | (1 << 3) | 3;
gettimeofday (&tv1, &tz);
t1 = (double) tv1.tv_sec + (double) tv1.tv_usec / 1000000;
memcpy (&buf[40], tonetnum ((unsigned long) tv1.tv_sec + EPOCH_DIFF), 4);
memcpy (&buf[44], tonetnum (usec2frac (tv1.tv_usec)), 4);
count = 0;
while(1){
FD_ZERO(&rd_fd);
FD_ZERO(&wr_fd);
time_out.tv_sec = 0;
time_out.tv_usec = 500000;
FD_SET(udp, &rd_fd);
FD_SET(udp, &wr_fd);
len = send (udp, buf, 48, 0);
if (len == -1)
{
printf("send error/n");
now = time (NULL);
if (errstart == 0)
errstart = now;
r = close (udp);
return 0;
}
if(count++ > 20){
printf("count too much/n");
close(udp);
return 0;
}
if(select(udp + 1, &rd_fd, NULL, NULL, &time_out) <= 0){
continue;
}
if(FD_ISSET(udp, &rd_fd)){
len = recv (udp, &buf, 60, 0);
if (len == -1)
{
now = time(NULL);
if (errstart == 0)
errstart = now;
r = close (udp);
return 0;
}
gettimeofday (&tv4, &tz);
t4 = (double) tv4.tv_sec + (double) tv4.tv_usec / 1000000;
tv2.tv_sec = fromnetnum (&buf[32]) - EPOCH_DIFF;
tv2.tv_usec = frac2usec (fromnetnum (&buf[36]));
t2 = (double) tv2.tv_sec + (double) tv2.tv_usec / 1000000;
tv3.tv_sec = fromnetnum (&buf[40]) - EPOCH_DIFF;
tv3.tv_usec = frac2usec (fromnetnum (&buf[44]));
t3 = (double) tv3.tv_sec + (double) tv3.tv_usec / 1000000;
toff = (t2 + t3 - t1 - t4) / 2;
if(mark == 0){
tnew = t4 + toff;
tvnew.tv_usec = (long long) (tnew * 1000000) % 1000000;
tvnew.tv_sec = ((long long) (tnew * 1000000) - tvnew.tv_usec) / 1000000;
settimeofday (&tvnew, &tz);
mark = 1;
}
if(mark == 1){
cmpval.tv_usec = (long long) (tnew * 1000000) % 1000000;
cmpval.tv_sec = ((long long) (tnew * 1000000) - cmpval.tv_usec) / 1000000;
if(cmpval.tv_sec - tvnew.tv_sec < 25){
settimeofday (&cmpval, &tz);
nowtime();
close(udp);
return toff;
}else{
mark = 0;
continue;
}
}
}
}
}
就是这样的,配一下协议头,然后发送给公网上的ntp_server,有时候第一次得到的是不正确的时间,所以取两次时间!!!!!