使用go对NTP发起请求获取当前时间
package main
import (
"encoding/binary"
"fmt"
"log"
"net"
"time"
)
// Packet 定义一个结构体,用于表示 NTP 数据包
type Packet struct {
Settings uint8 // 设置字段
Stratum uint8 // 层级字段
Poll int8 // 轮询字段
Precision int8 // 精度字段
RootDelay uint32 // 根延迟字段
RootDispersion uint32 // 根离散字段
ReferenceID uint32 // 参考 ID 字段
RefTimeSec uint32 // 参考时间秒部分
RefTimeFrac uint32 // 参考时间分数部分
OrigTimeSec uint32 // 原始时间秒部分
OrigTimeFrac uint32 // 原始时间分数部分
RxTimeSec uint32 // 接收时间秒部分
RxTimeFrac uint32 // 接收时间分数部分
TxTimeSec uint32 // 传输时间秒部分
TxTimeFrac uint32 // 传输时间分数部分
}
func NewPacket() *Packet {
return &Packet{}
}
func NewPacketSettings(settings uint8) *Packet {
return &Packet{Settings: settings}
}
// 定义 NTP 纪元时间与 UNIX 纪元时间的偏移量
const ntpEpochOffset = 2208988800
var (
host = "pool.ntp.org"
timeout = 15 * time.Second
)
// sendRequest 函数用于发送 NTP 请求
func sendRequest(conn net.Conn, req *Packet) error {
return binary.Write(conn, binary.BigEndian, req) // 以大端字节序将请求包写入连接
}
// readResponse 函数用于读取 NTP 响应
func readResponse(conn net.Conn, rsp *Packet) error {
return binary.Read(conn, binary.BigEndian, rsp) // 以大端字节序从连接读取响应包
}
// parseTime 函数用于解析 NTP 响应中的时间
func parseTime(rsp *Packet) time.Time {
secs := float64(rsp.TxTimeSec) - ntpEpochOffset // 计算自 UNIX 纪元的秒数
nanos := (int64(rsp.TxTimeFrac) * 1e9) >> 32 // 计算秒的小数部分
return time.Unix(int64(secs), nanos) // 返回完整的时间
}
// GetCurrentTime Ntp 函数用于从 NTP 服务器获取当前时间
func GetCurrentTime() {
// 创建一个 UDP 连接到指定的 NTP 服务器
conn, err := net.Dial("udp", fmt.Sprintf("%s:123", host))
if err != nil {
log.Fatalf("Failed to connect: %v", err) // 连接失败则记录错误并退出
}
defer conn.Close() // 函数结束时关闭连接
// 设置连接的读写超时时间为 15 秒
if err := conn.SetDeadline(time.Now().Add(timeout)); err != nil {
log.Fatalf("Failed to set deadline: %v", err) // 设置超时失败则记录错误并退出
}
req := NewPacketSettings(0x1B) // 创建一个 NTP 请求包
// 发送请求包到 NTP 服务器
if err := sendRequest(conn, req); err != nil {
log.Fatalf("Failed to send request: %v", err) // 发送请求失败则记录错误并退出
}
rsp := NewPacket() // 创建一个空的 NTP 响应包
// 从 NTP 服务器读取响应包
if err := readResponse(conn, rsp); err != nil {
log.Fatalf("Failed to read server response: %v", err) // 读取响应失败则记录错误并退出
}
currentTime := parseTime(rsp) // 解析响应包中的时间
fmt.Printf("Current time: %v\n", currentTime) // 打印当前时间
fmt.Println(currentTime.Format("2006-01-02 15:04:05")) // 或者格式化打印
}
func main() {
GetCurrentTime()
}
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/18326525
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2023-07-27 go实现对容器日志的读取并通过api展示