This is a creation in Article, where the information may have evolved or changed. After some research on network programming, I met an article titled Let's Make a NTP Client in C, written by David Lettier (lettier). This article inspired me to use go to do something similar. > The code mentioned in this blog post is here [Https://github.com/vladimirvivien/go-ntp-client] (https://github.com/vladimirvivien/go-ntp-client). This blog post describes the structure of a (real) NTP client, written in the Go language. It encapsulates, encapsulates, sends and receives NTP packets from the remote NTP server based on the UDP protocol through the Encoding/binary library. You can learn more about the NTP protocol by [here] (http://www.ntp.org/), or read the [RFC5905] (https://tools.ietf.org/html/rfc5905) specification, research one that implements more features, (possibly) better client [HTTPS://GITHUB.COM/BEEVIK/NTP] (HTTPS://GITHUB.COM/BEEVIK/NTP) than the Go NTP client. The concept of NTP packet structure time synchronization is very complex and I can't fully understand it, and it's beyond the scope of this blog post. Fortunately, the packet format used by NTP is simple and small enough for the client. The following figure shows the packet format for NTP v4. Regarding this blog post, we only focus on the first 48 bytes, ignoring the V4 version of the extended section. [NTP v4 Data Format (abbreviated)-https://tools.ietf.org/html/rfc5905] (https://raw.githubusercontent.com/studygolang/gctt-images/master/go-ntp/NTP-v4-data-format.png) The NTP V4 Data Format (abbreviated)-https://tools.ietf.org/html/rfc5905## NTP package client and the corresponding service side both use the same package format mentioned above. The following structure defines the NTP package and its properties, corresponding to the format one by one mentioned above. "' GotypePacket struct {Settings uint8//Leap yr indicator, ver number, and modestratum uint8//stratum of local clockpoll int8/ /poll exponentprecision int8//Precision Exponentrootdelay uint32//root delayrootdispersion uint32//root Dispersionr Eferenceid UInt32//reference idreftimesec UInt32//reference timestamp Secreftimefrac uint32//reference timestamp FRA Ctionalorigtimesec UInt32//Origin time Secsorigtimefrac UInt32//Origin time Fractionalrxtimesec UInt32//Receive Time Secsrxtimefrac UInt32//Receive time FRACTXTIMESEC UInt32//Transmit time Secstxtimefrac uint32//Transmit Time frac} ' "# # Start UDP connection Next, we use net through the UDP protocol. The Dial function starts a socket, contacts the NTP server, and sets a 15-second time-out. "' Goconn, err: = Net. Dial ("UDP", host) if err! = Nil {log. Fatal ("Failed to connect:", err)}defer Conn. Close () If ERR: = conn. Setdeadline (time. Now (). ADD (* time. Second)); Err! = Nil {log. Fatal ("Failed to set deadline:", Err)} ' # # Gets the time from the server before sending the request packet to the server, the first byte is the configuration used to set up the communication, we use the 0x1B (or binary 00011011) here, representing the client mode as 3,nTP version is 3, run year is 0, as follows: "' go//configure request settings by specifying the first byte as//xx 011 011 (or 0x1B)//| | +--Client Mode (3)//| +-----Version (3)//+--------Leap year indicator, 0 no warningreq: = &packet{settings:0x1b} "Next, we use binary library to go from The packet structure is encapsulated into a byte stream and sent out in the big-endian format. "' goif err: = Binary. Write (conn, binary. Bigendian, req); Err! = Nil {log. Fatalf ("Failed to send request:%v", Err)} ' # # from the server read time next, we use binary packets to automatically unpack the byte stream read from the server to the corresponding packet structure. "' GORSP: = &packet{}if err: = Binary. Read (conn, binary. Bigendian, RSP); Err! = Nil {log. Fatalf ("Failed to read server response:%v", Err)} ' # # parsing time in this super-ordinary example, we only have a transmit in the Date field (RSP. Txtimesec and Rsptxtimefrac) are interested in the time they are emitted from the server. But we cannot use them directly, we must first turn to Unix time. Unix time is an era that began in 1970 (or the number of seconds starting in 1970). However, NTP uses a different era, the number of seconds since 1900. Therefore, the value obtained from the NTP server should be correctly translated into Unix time must be reduced by the number of seconds (1970-1900), or 2,208,988,800 seconds, in this 70-year period. "' Goconst ntpepochoffset = 2208988800...secs: = float64 (RSP). TXTIMESEC)-Ntpepochoffsetnanos: = (Int64 (RSP). TxtimEFRAC) * 1e9) >> ' NTP value fraction part turns into nanoseconds. In this trivial case, this is optional and shows only for completeness. # # shows the time finally, the function times. Unix is used to create a fraction of a second using secs, fractional portions using the Nanos value of the time. The time will then be printed to the terminal. "' Gofmt. Printf ("%v\n", time. Unix (Int64 (secs), Nanos) "# # # Conclusion This blog post shows a common example of NTP clients. Describes how to use the Encoding/binary library to easily turn a struct into byte form. Instead, we use binary libraries to stream a byte into the corresponding struct value. This NTP client is not yet a product that can be used in a production environment, after all, it lacks many of the features specified by the NTP specification. Most of the fields returned from the server are ignored. You can get a more complete NTP client with Go written from [here] (HTTPS://GITHUB.COM/BEEVIK/NTP).
via:https://medium.com/learning-the-go-programming-language/lets-make-an-ntp-client-in-go-287c4b9a969f
Author: Vladimir Vivien Translator: gogeof proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
584 reads ∙2 likes