前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang ipc 通信_golang 2.0

golang ipc 通信_golang 2.0

作者头像
全栈程序员站长
发布2022-11-08 11:13:13
9430
发布2022-11-08 11:13:13
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输,使用的UDP端口号为123。

使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。

对于运行NTP的本地系统,既可以接收来自其他时钟源的同步,又可以作为时钟源同步其他的时钟,并且可以和其他设备互相同步。

golang ipc 通信_golang 2.0
golang ipc 通信_golang 2.0

其实NTP协议是很简单的协议,据说很快就要被代替了,之前还写过一个python解析flv协议文件代码,这些应用层协议都是开放的,不是私有的,知道协议是很容易解析出的,不说废话了

ntp.go

代码语言:javascript
复制
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

代码语言:javascript
复制
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://javaforall.cn/182866.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档