十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
#include#include #include #include #include #include #include #include #include #include #include #include #include #define NTP_PORT 123 /*NTP專用端口號(hào)字符串*/ #define TIME_PORT 37 /* TIME/UDP端口號(hào) */ #define NTP_SERVER_IP "61.135.250.78" /*國(guó)家授時(shí)中心IP*/ #define NTP_PORT_STR "123" /*NTP專用端口號(hào)字符串*/ #define NTPV1 "NTP/V1" /*協(xié)議及其版本號(hào)*/ #define NTPV2 "NTP/V2" #define NTPV3 "NTP/V3" #define NTPV4 "NTP/V4" #define TIME "TIME/UDP" #define NTP_PCK_LEN 48 #define LI 0 #define VN 3 #define MODE 3 #define STRATUM 0 #define POLL 4 #define PREC -6 #define JAN_1970 0x83aa7e80 /* 1900年~1970年之間的時(shí)間秒數(shù) */ #define NTPFRAC(x) (4294 * (x) + ((1981 * (x)) >> 11)) #define USEC(x) (((x) >> 12) - 759 * ((((x) >> 10) + 32768) >> 16)) typedef struct _ntp_time { unsigned int coarse; unsigned int fine; } ntp_time; struct ntp_packet { unsigned char leap_ver_mode; unsigned char startum; char poll; char precision; int root_delay; int root_dispersion; int reference_identifier; ntp_time reference_timestamp; ntp_time originage_timestamp; ntp_time receive_timestamp; ntp_time transmit_timestamp; }; char protocol[32]; /*構(gòu)建NTP協(xié)議包*/ int construct_packet(char *packet) { char version = 1; long tmp_wrd; int port; time_t timer; strcpy(protocol, NTPV3); /*判斷協(xié)議版本*/ if(!strcmp(protocol, NTPV1)||!strcmp(protocol, NTPV2) ||!strcmp(protocol, NTPV3)||!strcmp(protocol, NTPV4)) { memset(packet, 0, NTP_PCK_LEN); port = NTP_PORT; /*設(shè)置16字節(jié)的包頭*/ version = protocol[6] - 0x30; tmp_wrd = htonl((LI << 30)|(version << 27) |(MODE << 24)|(STRATUM << 16)|(POLL << 8)|(PREC & 0xff)); memcpy(packet, &tmp_wrd, sizeof(tmp_wrd)); /*設(shè)置Root Delay、Root Dispersion和Reference Indentifier */ tmp_wrd = htonl(1<<16); memcpy(&packet[4], &tmp_wrd, sizeof(tmp_wrd)); memcpy(&packet[8], &tmp_wrd, sizeof(tmp_wrd)); /*設(shè)置Timestamp部分*/ time(&timer); /*設(shè)置Transmit Timestamp coarse*/ tmp_wrd = htonl(JAN_1970 + (long)timer); memcpy(&packet[40], &tmp_wrd, sizeof(tmp_wrd)); /*設(shè)置Transmit Timestamp fine*/ tmp_wrd = htonl((long)NTPFRAC(timer)); memcpy(&packet[44], &tmp_wrd, sizeof(tmp_wrd)); return NTP_PCK_LEN; } else if (!strcmp(protocol, TIME))/* "TIME/UDP" */ { port = TIME_PORT; memset(packet, 0, 4); return 4; } return 0; } /*獲取NTP時(shí)間*/ int get_ntp_time(int sk, struct addrinfo *addr, struct ntp_packet *ret_time) { fd_set pending_data; struct timeval block_time; char data[NTP_PCK_LEN * 8]; int packet_len, data_len = addr->ai_addrlen, count = 0, result, i, re; if (!(packet_len = construct_packet(data))) { return 0; } /*客戶端給服務(wù)器端發(fā)送NTP協(xié)議數(shù)據(jù)包*/ if ((result = sendto(sk, data, packet_len, 0, addr->ai_addr, data_len)) < 0) { perror("sendto"); return 0; } /*調(diào)用select()函數(shù),并設(shè)定超時(shí)時(shí)間為1s*/ FD_ZERO(&pending_data); FD_SET(sk, &pending_data); block_time.tv_sec=10; block_time.tv_usec=0; if (select(sk + 1, &pending_data, NULL, NULL, &block_time) > 0) { /*接收服務(wù)器端的信息*/ if ((count = recvfrom(sk, data, NTP_PCK_LEN * 8, 0, addr->ai_addr, &data_len)) < 0) { perror("recvfrom"); return 0; } if (protocol == TIME) { memcpy(&ret_time->transmit_timestamp, data, 4); return 1; } else if (count < NTP_PCK_LEN) { return 0; } /* 設(shè)置接收NTP包的數(shù)據(jù)結(jié)構(gòu) */ ret_time->leap_ver_mode = ntohl(data[0]); ret_time->startum = ntohl(data[1]); ret_time->poll = ntohl(data[2]); ret_time->precision = ntohl(data[3]); ret_time->root_delay = ntohl(*(int*)&(data[4])); ret_time->root_dispersion = ntohl(*(int*)&(data[8])); ret_time->reference_identifier = ntohl(*(int*)&(data[12])); ret_time->reference_timestamp.coarse = ntohl (*(int*)&(data[16])); ret_time->reference_timestamp.fine = ntohl(*(int*)&(data[20])); ret_time->originage_timestamp.coarse = ntohl(*(int*)&(data[24])); ret_time->originage_timestamp.fine = ntohl(*(int*)&(data[28])); ret_time->receive_timestamp.coarse = ntohl(*(int*)&(data[32])); ret_time->receive_timestamp.fine = ntohl(*(int*)&(data[36])); ret_time->transmit_timestamp.coarse = ntohl(*(int*)&(data[40])); ret_time->transmit_timestamp.fine = ntohl(*(int*)&(data[44])); return 1; } /* end of if select */ return 0; } /* 修改本地時(shí)間 */ int set_local_time(struct ntp_packet * pnew_time_packet) { struct timeval tv; tv.tv_sec = pnew_time_packet->transmit_timestamp.coarse - JAN_1970; tv.tv_usec = USEC(pnew_time_packet->transmit_timestamp.fine); return settimeofday(&tv, NULL); } int main() { int sockfd, rc; struct addrinfo hints, *res = NULL; struct ntp_packet new_time_packet; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; /*調(diào)用getaddrinfo()函數(shù),獲取地址信息*/ rc = getaddrinfo(NTP_SERVER_IP, NTP_PORT_STR, &hints, &res); if (rc != 0) { perror("getaddrinfo"); return 1; } /* 創(chuàng)建套接字 */ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd <0 ) { perror("socket"); return 1; } /*調(diào)用取得NTP時(shí)間的函數(shù)*/ if (get_ntp_time(sockfd, res, &new_time_packet)) { /*調(diào)整本地時(shí)間*/ if (!set_local_time(&new_time_packet)) { printf("NTP client success!\n"); } } close(sockfd); return 0; }