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 ...
随机推荐
- LeetCode.接雨水
题外话:LeetCode上一个测试用例总是通不过(我在文章末贴出通不过的测试用例),给的原因是超出运行时间,我拿那个测试用例试了下2.037ms运行完.我自己强行给加了这句: && m ...
- pptpd免radius限速、限连接+自由定制功能脚本
因为就几个用户懒得上radius,所以手写了一个用户管理脚本. 脚本很简单,具体直接看repo吧. https://github.com/esxgx/pptpd-exscripts
- CF666E Forensic Examination [后缀自动机,线段树合并]
洛谷 Codeforces 思路 最初的想法:后缀数组+区间众数,似乎并不能过. 既然后缀数组不行,那就按照套路建出广义SAM,然后把\(S\)放在上面跑,得到以每个点结尾会到SAM上哪个节点. 询问 ...
- 让oracle数据库的表的id自动递增
1.创建递增序列 CREATE SEQUENCE ID_ADD(序列名称)INCREMENT BY 1START WITH 1MINVALUE 1NOMAXVALUE; 2.创建触发器绑定到表上cr ...
- sortable.js 拖拽排序及配置项说明
// 拖动排序 $(function() { /*排序*/ //排序 // Simple list ]; new Sortable(list, { group: "name", a ...
- Rest分页接口开发
简单描述:需求说后端写一个XX数据的分页接口,给前端口调用,其实有一个PageHelper的工具类可以直接使用但是老大不让用,得用sql写,.小Kiss啦.直接上代码 代码: //Controller ...
- 2018-2019-2 网络对抗技术 20165323 Exp6 信息搜集与漏洞扫描
一.实验内容 二.实验步骤 1.各种搜索技巧的应用 2.DNS IP注册信息的查询 3.基本的扫描技术 主机发现 端口扫描 OS及服务版本探测 具体服务的查点 4.漏洞扫描 三.实验中遇到的问题 四. ...
- Redis实战 - 4.Key
Redis 键(key) Redis 键命令用于管理 redis 的键. DEL key 该命令用于在 key 存在时删除 key. 127.0.0.1:6379> set w3ckey red ...
- 【ES6】Generator+Promise异步编程
一.概念 首先我们要理解Generator和Promise的概念. Generator:意思是生成器,可以在函数内部通过yeild来控制语句的执行或暂停状态. *Foo(){ yeild consol ...
- Excel—图表函数
OFFSET(引用函数)它可以找一个区域,把一个区域的值都拿回来 函数语法:OFFSET(从哪个单元格开始,这个单元格下移多少行开始,然后现在的位置再往右多少列开始,要取的值是现在的位置开始下移多少行 ...