This is a creation in Article, where the information may have evolved or changed.
File Project Main.go
Package Main
Import (
"Encoding/binary"
"FMT"
"NET"
"OS"
"Os/signal"
"Sync"
"Time"
)
Const (
NTP_SERVER_IP = "time.windows.com"/*NTP ip*/
NTP_PORT_STR = "123"/*NTP dedicated port number String */
Ntp_pck_len = 48
LI = 0
VN = 3
MODE = 3
Stratum = 0
POLL = 4
PREC =-6
jan_1970 = 0X83AA7E80/* Time in seconds between 1900/~1970 years */
)
Func Ntpfrac (x Int64) Int64 {
Return (4294* (x) + ((1981 * (x)) >> 11))
}
Func USEC (x Int64) Int64 {
Return ((((x) >>)-759* (((((((((((((((((((x)) +32768) >>16))
}
Type ntp_time struct {
Coarse UInt32
Fine UInt32
}
Type Ntp_packet struct {
Leap_ver_mode byte
Startum byte
Poll byte
Precision Byte
Root_delay int
root_dispersion int
Reference_identifier int
Reference_timestamp Ntp_time
Originage_timestamp Ntp_time
Receive_timestamp Ntp_time
Transmit_timestamp Ntp_time
}
VAR protocol []byte
Func Construct_packet () ([]byte, int) {
Reqdata: = Make ([]byte, Ntp_pck_len)
Set the 16-byte header
Head: = (LI << 30) | (VN << 27) | (MODE << 24) | (Stratum << 16) | (POLL << 8) | (PREC & 0xFF)
Binary. Bigendian.putuint32 (Reqdata[0:4], UInt32 (head))
Set root Delay, root dispersion, and reference indentifier
Binary. Bigendian.putuint32 (Reqdata[4:8], UInt32 (1<<16))
Binary. Bigendian.putuint32 (Reqdata[8:12], UInt32 (1<<16))
Binary. Bigendian.putuint32 (Reqdata[12:16], UInt32 (1<<16))
Setting the timestamp section
Timeori: = jan_1970 + time. Now (). Unix ()
Set transmit Timestamp Coarse
Binary. Bigendian.putuint32 (reqdata[40:44], UInt32 (Timeori))
Set transmit Timestamp fine
Binary. Bigendian.putuint32 (reqdata[44:48], UInt32 (Ntpfrac (Timeori)))
Return Reqdata, Ntp_pck_len
}
Func Main () {
protocol = make ([]byte, 32)
Resolve Address
Fmt. PRINTLN ("NTP begin NTC ...")
UDPADDR, Errdata: = Net. RESOLVEUDPADDR ("UDP", ntp_server_ip+ ":" +ntp_port_str)
If nil! = Errdata {
Fmt. Printf ("NTP Connect err:%v\n", Errdata)
Return
}
Fmt. Println ("NTP after resolvetcpaddr ......:", UDPADDR)
Conn, Err: = Net. DIALUDP ("UDP", Nil, udpaddr)
If nil! = Err {
Fmt. Printf ("NTP net Connect error:%v\n", err)
Return
}
Fmt. Println ("NTP after dialudp ...")
Data, Packet_len: = Construct_packet ()
If Packet_len = = 0 {
Fmt. PRINTLN ("NTP packet len is 0")
Return
}
Fmt. PRINTLN ("NTP begin send:%V, data:%v", Packet_len, data)
Conn. Setwritedeadline (time. Now (). ADD (time. Second))
Size, ERR: = conn. Write (data)
If nil! = Err {
Fmt. Printf ("NTP Write data error:%v\n", err)
Return
} else {
Fmt. Printf ("NTP write Len:%v\n", size)
}
Fmt. Println ("After send")
Recvbody: = Make ([]byte, 4096)
Wait: = &sync. waitgroup{}
Wait. ADD (1)
Go func () {
Defer wait. Done ()
for {
Fmt. PRINTLN ("NTP begin read")
Conn. Setreaddeadline (time. Now (). ADD (time. Second))
Size, remoteaddr, err: = conn. READFROMUDP (Recvbody)
If nil! = Err {
Fmt. Printf ("NTP read data error:%v\n", err)
} else {
Fmt. Printf ("NTP read len:%v\n", size)
}
Fmt. Println ("NTP after read, remoteaddr:%v\n", remoteaddr.string (), recvbody[:size])
Break
}
}()
Wait. Wait ()
var Datastru ntp_packet
DataStru.transmit_timestamp.coarse = binary. Bigendian.uint32 (recvbody[40:44])-jan_1970
DataStru.transmit_timestamp.fine = UInt32 (USEC (Int64 (binary). Bigendian.uint32 (recvbody[44:48])))
Fmt. Println (Datastru)
//waiting to exit
c: = Make (chan os. Signal, 1)
signal. Notify (c, OS. Interrupt, OS. Kill)
<-c
fmt. Println ("NTP Receive ctrl-c")
}