The source of this article:
http://www.eefocus.com/html/10-04/94667s.shtml
10.4 Experimental Content--NTP protocol implementation
1. Experimental purposesThrough the implementation of NTP protocol, further mastering Linux network programming, and improve the ability of analysis and implementation of the Protocol, to participate in the completion of a comprehensive project to lay a good foundation.
2. Experimental content
The network Time Protocol (NTP) protocol is a protocol used to synchronize computer times, allowing computers to synchronize their servers or clock sources (such as quartz clocks, GPS, etc.), which can provide high precision time correction (LAN vs. standard times less than 1 milliseconds, Dozens of milliseconds on a wan, and can be used to prevent protocol attacks by means of encryption acknowledgement. NTP provides accurate time, first of all to have an accurate time source, this time should be international standard UTC. NTP can obtain UTC in time from atomic clocks, observatories, satellites, or from the Internet. This will have an accurate and reliable time source. Time is propagated at the level of the NTP server. All servers are grouped into different stratun (layers) in accordance with the distance from the external UTC source. Stratum-1 at the top, with external UTC access, while Stratum-2 gets time from Stratum-1, Stratum-3 gets time from Stratum-2, and so on, but the total number of stratum layers is limited to 15. All of these servers logically form a ladder-style architecture and connect to each other, while the Stratum-1 time server is the foundation of the entire system. The most important thing in the implementation of network protocol is to understand protocol data format. The NTP packet has 48 bytes, in which the NTP header is 16 bytes and the time stamp is 32 bytes. The protocol format is shown in Figure 10.9.
Figure 10.9 NTP protocol data format the meaning of its Protocol field is shown below.LI: Jump indicator, warning of impending close in the last day of the month (boudoir seconds).VN: Version number.Mode:Working mode. The field includes the following values: 0-reserved, 1-symmetric behavior, 3-client, server, 5-broadcast, 6-NTP control information. The NTP protocol has 3 modes of operation, namely primary/passive symmetric mode, client/server mode, broadcast mode. In primary/passive symmetric mode, there is a one-to-one connection, both sides can sync each other or be synchronized by the other side, the first issue of the application to establish a connection to work in the active mode, the other side of the work in the passive mode; the client/server mode is essentially the same as the primary/passive mode, except that the client is synchronized However, the server can not be synchronized with the client, in the broadcast mode, there are a one-to-many connection, the server regardless of the customer's work in which mode, will actively send out time information, customers adjust their time based on this information.Stratum: An overall recognition of the local clock level.Poll: A signed integer that represents the maximum interval between consecutive information.Precision: A signed integer representing the local clock accuracy.Root Delay: Represents a reciprocating total delay to the main reference source, which is a symbol fixed-point decimal with a 15~16 bit fraction.Root Dispersion: Represents a standard error that reaches the primary reference source at a time, which is an unsigned fixed-point decimal with a 15~16 bit of fractional decimal.Reference Identifier: Identify special reference sources.originate Timestamp: This is the time to request the server to detach the client, using the 64-bit time scale format.Receive Timestamp: This is the time to request the server to reach the client, using the 64-bit time scale format.Transmit Timestamp: This is the time to reply to the client to detach the server, using the 64-bit time scale format.Authenticator (Optional): When the NTP authentication mode is implemented, the primary identifier and the information Number field include the defined Information authentication Code (MAC) information. Because of the more time related operation in NTP protocol, in order to simplify the implementation process, in this experiment, only the network communication module of the client part of NTP protocol is required, that is, the construction of NTP protocol field is sent and received, and the operation of time related is not needed to be processed. The NTP protocol is a high level protocol for the OSI Reference Model, which is suitable for data transmission with UDP transmission protocol, and the special port number is 123. In the experiment, the National Time Service Center Server (IP address is 202.72.145.44) as the NTP (network times) server.3. Experiment Steps(1) Draw the flow chart. The implementation process for the simple NTP client is shown in Figure 10.10.
Figure 10.10 Simple NTP Client flowchart
(2) Writing programs. The specific code is as follows:* NTP.C * * #include <sys/socket.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include & lt;errno.h> #include <string.h> #include <sys/un.h> #include <sys/time.h> #include <sys/ ioctl.h> #include <unistd.h> #include <netinet/in.h> #include <string.h> #include <netdb.h> #define NTP_PORT 123 /*NTP Dedicated Port number String */#define Time _port 37 /* TIME/UDP Port number * * * #define NTP_SERVER_IP "210.72.145.44" /* National Timing Center ip*/#define NTP_PORT_STR "123" /*NTP private Port number string* * #define NTPV1 "ntp/ V1 " /* protocol and its version number */#define NTPV2 "Ntp/v2" #define NTPV3 "Ntp/v3" #define NTPV4 "NTP/V4" #define TIME "TIME/UDP" #define Ntp_pck_len #define LI 0 #define VN 3 #define MODE 3 #de Fine stratum 0 #define POLL 4 #define PREC-6 #define JAN_1970&NBSP;0X83AA7E80&NBSP;/* The number of seconds between 1900 ~1970 years */#defin e Ntpfrac (x) (4294 * (x) + ((1981 * (x)) >> 11)
#define USEC (x) ((x) >>)-759 * (((((x) >>) + 32768) >>)) typedef struct _NTP_TI Me {
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]; /* Build NTP protocol package */int construct_packet (char *packet) {
char Version = 1;
Long TMP_WRD; int port; time_t timer; strcpy (protocol, NTPV3); /* Judge the protocol version * *
if (!strcmp (protocol, NTPV1) | |! strcmp (protocol, NTPV2)
||! strcmp (Protocol, NTPV3) | |! strcmp (Protocol, NTPV4)) {memset (packet, 0, Ntp_pck_len); Port = Ntp_port; /* Set 16 bytes of Baotou */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)); /* Set root Delay, root dispersion and reference indentifier * *
TMP_WRD = htonl(1<<16);
memcpy (&packet[4], &TMP_WRD, sizeof (TMP_WRD));
memcpy (&packet[8], &TMP_WRD, sizeof (TMP_WRD)); /* Set TIMESTAMP part * * Time (&timer); /* Set transmit Timestamp coarse*/
TMP_WRD = htonl(jan_1970 + (long) timer);
memcpy (&packet[40], &TMP_WRD, sizeof (TMP_WRD)); /* Set 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; }/* Get NTP time/*
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; * * Client sends NTP protocol packet to server
if (result = sendto (SK, data,
Packet_len, 0, addr->ai_addr, Data_len) < 0) {perror ("sendto");
return 0; /* Call the Select () function and set the timeout time to 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) {/* Receive server-side information/*
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; /* Set the data structure that receives the NTP packet/*
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; } */* Modify local time * *
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; /* Call the Getaddrinfo () function to get the address information * *
rc = getaddrinfo (ntp_server_ip, Ntp_port_str, &hints, &res); if (RC!= 0) {perror ("getaddrinfo"); return 1; /* Create SOCKET/* *
SOCKFD = socket (res->ai_family, Res->ai_socktype, res->ai_protocol); if (sockfd <0) {perror ("socket"); return 1;
}/* Call the function that gets the NTP time * *
If (Get_ntp_time (SOCKFD, res, &new_time_packet)) {/* Adjust local time */if (!set_local_tim E (&new_time_packet)) {
printf ("NTP client success!\n"); } close (SOCKFD);
return 0;} to better observe the effect of the program, first use the date command to modify the system time, and then run the instance program. When you're done, check the system time, and you'll see that you've recovered the exact system time. The results of the specific operation are shown below. $ date-s "2001-01-01 1:00:00" January 01, 2001 Monday 01:00:00 EST $ Date January 2001 01 Day Monday 01:00:00 EST $./ NTP NTP client success! $ Date can display the current exact date and time.