golang ntp协议客户端
NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输,使用的UDP端口号为123。
使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。
对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。
相信文本介绍看多也厌倦了,就不多废话,直接上干活
ntp.go
package main import (
"bytes"
"encoding/binary"
) const (
UNIX_STA_TIMESTAMP = 2208988800
) /**
NTP协议 http://www.ntp.org/documentation.html
@author mengdj@outlook.com
*/
type Ntp struct {
//1:32bits
Li uint8 //2 bits
Vn uint8 //3 bits
Mode uint8 //3 bits
Stratum uint8
Poll uint8
Precision uint8
//2:
RootDelay int32
RootDispersion int32
ReferenceIdentifier int32
//64位时间戳
ReferenceTimestamp uint64 //指示系统时钟最后一次校准的时间
OriginateTimestamp uint64 //指示客户向服务器发起请求的时间
ReceiveTimestamp uint64 //指服务器收到客户请求的时间
TransmitTimestamp uint64 //指示服务器向客户发时间戳的时间
} func NewNtp() (p *Ntp) {
//其他参数通常都是服务器返回的
p = &Ntp{Li: 0, Vn: 3, Mode: 3, Stratum: 0}
return p
} /**
构建NTP协议信息
*/
func (this *Ntp) GetBytes() []byte {
//注意网络上使用的是大端字节排序
buf := &bytes.Buffer{}
head := (this.Li << 6) | (this.Vn << 3) | ((this.Mode << 5) >> 5)
binary.Write(buf, binary.BigEndian, uint8(head))
binary.Write(buf, binary.BigEndian, this.Stratum)
binary.Write(buf, binary.BigEndian, this.Poll)
binary.Write(buf, binary.BigEndian, this.Precision)
//写入其他字节数据
binary.Write(buf, binary.BigEndian, this.RootDelay)
binary.Write(buf, binary.BigEndian, this.RootDispersion)
binary.Write(buf, binary.BigEndian, this.ReferenceIdentifier)
binary.Write(buf, binary.BigEndian, this.ReferenceTimestamp)
binary.Write(buf, binary.BigEndian, this.OriginateTimestamp)
binary.Write(buf, binary.BigEndian, this.ReceiveTimestamp)
binary.Write(buf, binary.BigEndian, this.TransmitTimestamp)
//[27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
return buf.Bytes()
} func (this *Ntp) Parse(bf []byte, useUnixSec bool) {
var (
bit8 uint8
bit32 int32
bit64 uint64
rb *bytes.Reader
)
//貌似这binary.Read只能顺序读,不能跳着读,想要跳着读只能使用切片bf
rb = bytes.NewReader(bf)
binary.Read(rb, binary.BigEndian, &bit8)
//向右偏移6位得到前两位LI即可
this.Li = bit8 >> 6
//向右偏移2位,向右偏移5位,得到前中间3位
this.Vn = (bit8 << 2) >> 5
//向左偏移5位,然后右偏移5位得到最后3位
this.Mode = (bit8 << 5) >> 5
binary.Read(rb, binary.BigEndian, &bit8)
this.Stratum = bit8
binary.Read(rb, binary.BigEndian, &bit8)
this.Poll = bit8
binary.Read(rb, binary.BigEndian, &bit8)
this.Precision = bit8 //32bits
binary.Read(rb, binary.BigEndian, &bit32)
this.RootDelay = bit32
binary.Read(rb, binary.BigEndian, &bit32)
this.RootDispersion = bit32
binary.Read(rb, binary.BigEndian, &bit32)
this.ReferenceIdentifier = bit32 //以下几个字段都是64位时间戳(NTP都是64位的时间戳)
binary.Read(rb, binary.BigEndian, &bit64)
this.ReferenceTimestamp = bit64
binary.Read(rb, binary.BigEndian, &bit64)
this.OriginateTimestamp = bit64
binary.Read(rb, binary.BigEndian, &bit64)
this.ReceiveTimestamp = bit64
binary.Read(rb, binary.BigEndian, &bit64)
this.TransmitTimestamp = bit64
//转换为unix时间戳,先左偏移32位拿到64位时间戳的整数部分,然后ntp的起始时间戳 1900年1月1日 0时0分0秒 2208988800
if useUnixSec {
this.ReferenceTimestamp = (this.ReceiveTimestamp >> 32) - UNIX_STA_TIMESTAMP
if this.OriginateTimestamp > 0 {
this.OriginateTimestamp = (this.OriginateTimestamp >> 32) - UNIX_STA_TIMESTAMP
}
this.ReceiveTimestamp = (this.ReceiveTimestamp >> 32) - UNIX_STA_TIMESTAMP
this.TransmitTimestamp = (this.TransmitTimestamp >> 32) - UNIX_STA_TIMESTAMP
}
}
main.go
package main import (
"fmt"
"log"
"net"
) func main() {
var (
ntp *Ntp
buffer []byte
err error
ret int
)
//链接阿里云NTP服务器,NTP有很多免费服务器可以使用time.windows.com
conn, err := net.Dial("udp", "ntp1.aliyun.com:123")
defer func() {
if err := recover(); err != nil {
log.Println(err)
}
conn.Close()
}()
ntp = NewNtp()
conn.Write(ntp.GetBytes())
buffer = make([]byte, 2048)
ret, err = conn.Read(buffer)
if err == nil {
if ret > 0 {
ntp.Parse(buffer, true)
fmt.Println(fmt.Sprintf(
"LI:%d\r\n版本:%d\r\n模式:%d\r\n精度:%d\r\n轮询:%d\r\n系统精度:%d\r\n延时:%ds\r\n最大误差:%d\r\n时钟表示:%d\r\n时间戳:%d %d %d %d\r\n",
ntp.Li,
ntp.Vn,
ntp.Mode,
ntp.Stratum,
ntp.Poll,
ntp.Precision,
ntp.RootDelay,
ntp.RootDispersion,
ntp.ReferenceIdentifier,
ntp.ReferenceTimestamp,
ntp.OriginateTimestamp,
ntp.ReceiveTimestamp,
ntp.TransmitTimestamp,
))
}
}
}
源码见:https://github.com/mengdj/ntp-go
golang ntp协议客户端的更多相关文章
- 通过NTP协议进行时间同步
最近发现手机的时间不是很准了,便到网上下了一个同步时间的小程序,简单了看了一下它的原理,是通过NTP协议来实现校时的,就顺便学习了一下NTP协议,用C#写了个简单的实现. NTP(Network Ti ...
- 实现基于NTP协议的网络校时功能
无论PC端还是移动端系统都自带时间同步功能,基于的都是NTP协议,这里使用C#来实现基于NTP协议的网络校时功能(也就是实现时间同步). 1.NTP原理 NTP[Network Time Protoc ...
- NTP 协议介绍
NTP协议 NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步.NTP基于UDP报文进行传输,使用 ...
- 保姆级别的RabbitMQ教程!包括Java和Golang两种客户端
目录 什么是AMQP 和 JMS? 常见的MQ产品 安装RabbitMQ 启动RabbitMQ 什么是Authentication(认证) 指定RabbitMQ的启动配置文件 如何让guest用户远程 ...
- 保姆级别的RabbitMQ教程!一看就懂!(有安装教程,送安装需要的依赖包,送Java、Golang两种客户端教学Case)
保姆级别的RabbitMQ教程!一看就懂!(有安装教程,送安装需要的依赖包,送Java.Golang两种客户端教学Case) 目录 什么是AMQP 和 JMS? 常见的MQ产品 安装RabbitM ...
- 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析
很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...
- 使用ntp协议同步本地时间(C语言)
使用ntp协议同步本地时间 同步服务器使用的东北大学网络授时服务:ntp.neu.edu.cn更多ntp服务器 http://www.ntp.org.cn/ 源代码来自网络,经本人精简ntp部分,供大 ...
- C#实现WebSocket协议客户端和服务器websocket sharp组件实例解析
看到这篇文章的题目,估计很多人都会问,这个组件是不是有些显的无聊了,说到web通信,很多人都会想到ASP.NET SignalR,或者Nodejs等等,实现web的网络实时通讯.有关于web实时通信的 ...
- yum仓库客户端搭建和NTP时间同步客户端配置
一.yum仓库客户端搭建 yum源仓库搭建分为服务器端和客户端. 服务端主要提供软件(rpm包)和yumlist.也就是提供yum源的位置.一般是通过http或者ftp提供位置. 客户端的配置:yum ...
随机推荐
- 关于this绑定的四种方式
一.前言 我们每天都在书写着有关于this的javascript代码,似懂非懂地在用着.前阵子在看了<你不知道的JavaScript上卷>之后,也算是被扫盲了一边关于this绑定的四种方式 ...
- 第十二节,OpenCV学习(一)图像的读取、显示、保存
一.读取图像 所谓的图像就是一个数组,对图像的处理就是对数字的处理 import cv2 import numpy as np img = cv2.imread('dog.jpg') print(im ...
- java 日常学习记录
前言:记录自己初学java 遇到的问题. 环境(win10 开始安装的IDEA,net 开发者 )学习网址:http://how2j.cn/stage/14.html (不是打广告) 特别是对初学 ...
- 【转】Setting up SDL 2 on Visual Studio 2010 Ultimate
from: Lazy Foo'Productions - Setting up SDL 2 on Visual Studio 2010 Ultimate 1)First thing you need ...
- MVC或WebAPI发布后报错404问题的总结
在MVC项目或者webAPI项目发布之后有时会发生404错误.针对这种错误的解决办法: 解决办法1(不推荐):在webconfig中 <system.webServer> 节点下 添加 & ...
- [转]Jupyter默认目录和默认浏览器修改
转摘于:https://blog.csdn.net/caterfreelyf/article/details/79774311 1.打开cmd,首先进入到Jupyter的安装目录,我的是在D:\Pyt ...
- 直流滤波器 verilog
// dc filter- y(n) = c*x(n) + (1-c)*y(n-1) `timescale 1ps/1ps module ad_dcfilter #( // data path dis ...
- Python爬去有道翻译
注:传入的类型为POST类型,所以需要使用urllib.parse.urlencode(),将字典转换成URL可用参数: 使用json.loads(),将输出的json格式,转换为字典类型 impor ...
- 网络流24题——魔术球问题 luogu 2765
题目描述:这里 这道题是网络流问题中第一个难点,也是一个很重要的问题 如果直接建图感觉无从下手,因为如果不知道放几个球我就无法得知该如何建图(这是很显然的,比如我知道 $1+48=49=7^2$ ,可 ...
- 客户端和浏览器都不能连接SVN服务器
错误提示 1.在对话框中提示 2.在As上提示 Error:svn: E731001: Unable to connect to a repository at URL 'https://XXX/sv ...