Let’s Make an NTP Client in Go

Vladimir Vivien
Jan 4, 2018 · 4 min read

A word about NTP

NTP v4 data format (abbreviated) — https://tools.ietf.org/html/rfc5905

NTP Packet

type packet struct {
Settings uint8 // leap yr indicator, ver number, and mode
Stratum uint8 // stratum of local clock
Poll int8 // poll exponent
Precision int8 // precision exponent
RootDelay uint32 // root delay
RootDispersion uint32 // root dispersion
ReferenceID uint32 // reference id
RefTimeSec uint32 // reference timestamp sec
RefTimeFrac uint32 // reference timestamp fractional
OrigTimeSec uint32 // origin time secs
OrigTimeFrac uint32 // origin time fractional
RxTimeSec uint32 // receive time secs
RxTimeFrac uint32 // receive time frac
TxTimeSec uint32 // transmit time secs
TxTimeFrac uint32 // transmit time frac
}

Setup UDP Connection

conn, err := net.Dial("udp", host)
if err != nil {
log.Fatal("failed to connect:", err)
}
defer conn.Close()
if err := conn.SetDeadline(
time.Now().Add(15 * time.Second)); err != nil {
log.Fatal("failed to set deadline: ", err)
}

Request time from server

// configure request settings by specifying the first byte as
// 00 011 011 (or 0x1B)
// | | +-- client mode (3)
// | + ----- version (3)
// + -------- leap year indicator, 0 no warning
req := &packet{Settings: 0x1B}
if err := binary.Write(conn, binary.BigEndian, req); err != nil {
log.Fatalf("failed to send request: %v", err)
}

Read time from server

rsp := &packet{}
if err := binary.Read(conn, binary.BigEndian, rsp); err != nil {
log.Fatalf("failed to read server response: %v", err)
}

Parse the time

const ntpEpochOffset = 2208988800
...
secs := float64(rsp.TxTimeSec) - ntpEpochOffset
nanos := (int64(rsp.TxTimeFrac) * 1e9) >> 32

Display the time

fmt.Printf("%v\n", time.Unix(int64(secs), nanos))

Conclusion

Learning the Go Programming Language

Short and insightful posts for newcomers learning the Go programming language

Vladimir Vivien

Written by

Software Eng • Go Programming • Kubernetes • Author http://golang.fyi

Learning the Go Programming Language

Short and insightful posts for newcomers learning the Go programming language