SNTP原理讲解 客户端 C语言实现
1.定义
SNTP(Simple Network Time Protocal简单网络时间协议),用于跨广域网或局域网同步时间的协议,具有较高的精确度(几十毫秒)
这里给出SNTP的详细定义和解释,以及基于C语言的SNTP客户端实现代码:SNTP code 实际测试过
小工具:IP查域名,地址;计算2个日期间的 间隔数值
1.1 SNTP与NTP区别:
1.SNTP协议相对于NTP,都是优化了网络传播延时的影响,但是没有像NTP一样考虑 冗余服务器 和 校正时钟频率误差功能
2.NTP可跨平台和跨系统,精度较高,1-50ms精度;提供认证机制,安全机制高
3.SNTP是NTP简化版本,精度在1s左右,SNTP通常与网络叶子节点设备进行时间同步
4.SNTP与NTP报文完全一致
1.1.1 SNTP采用client - server模式,使用单播/广播:
1. 单播是定期与SNTP server交互获取时间差进行校时
2. 广播是SNTP server定期向多播地址发送时间信息,client监听多播地址来获取时间进行同步
1.2 SNTP校时原理:
T1,T2,T3,T4均是时间戳,用以计算各自的时间差
t1与t2之间的时间差(包在网络上走了个来回):| [(T2-T1)-(T4-T3)] | / 2,此处的| | 表示取绝对值
数据包在网络上的传播时间: (T2-T1) + (T4-T3)
注意:NTP时间戳从1900年开始记秒数,而UNIX时间戳从1970年开始记秒数,即记录到NTP结构体中的时间要加上JAN_1970(1900到1970共70年的秒数),而从起获取出来需减掉JAN_1970
1.2.1 Demo例子:
DeviceA与DeviceB在时间同步前,A:10:00:00am,B:11:00:00am,将B作为timeserver来校准A的时间,假设NTP报文在A和B之间单向传输所需要的时间为1s,B接收到发送出去也需要1s
A发NTP报文至B,带有10:00:00的时间戳,T1=10:00:00am;
NTP报文到达B后,B加上时间戳T2=11:00:01am;
NTP报文离开B时,B再加上时间戳T3=11:00:02am;
A收到NTP报文后,加上A本地的时间戳T4=10:00:03;
A与B时间差:[(T2-T1)-(T4-T3)]/2=1h
数据包在网络上的传播时间: (T2-T1) + (T4-T3)=2s
所以,client的真正的时间计算应该是 T3 + [(T4-T1)-(T3-T2)] / 2 = T3 + [(T2-T1)+(T4-T3)] / 2,即:T3 server 的时间戳 + 网络单程时延的数值即可
或者是 T4 + [(T2-T1)+(T3-T4)] / 2,不过还是上面的以T3来算的公式是最简明,最符合直观上的逻辑
1.3 NTP报文格式:
LI:当前时间闰秒标志。字段长度为2位整数,只在服务器端有效
0:无警告 |
1:最后一分钟是61秒; |
2:最后一分钟是59秒; |
3:警告(时钟没有同步) |
VN:表示NTP的版本号,长度为3比特,可以是3或者是4
0:保留 | 1:对称主动 | 2:对称被动 | 3:客户 |
4:服务器 | 5:广播 | 6:保留为NTP控制信息 | 7:保留为用户定义 |
stratum:指从stratum-1时间服务器(如从GPS取得的标准时间所存储的server) 至 client所经过的server个数,类似于路由器经过的跳数,数目越小,精度越高;只在服务器端有效,字段长度为8个比特(unsigned char型)
0:故障信息 | 1:一级服务器 | 2-15:二级服务器 | 6-255:保留 |
Poll Interval:指示数据包的最大时间间隔,以秒为单位,作为2的指数方的指数部分,该字段只在服务器端有效。字段长度为8位整数,取值范围从4-17,即16秒到131,072秒
Precision:指示系统时钟的精确性,以秒为单位,作为2的指数方的指数部分,该字段只在服务器端有效。字段长度为8位有符号整数,取值范围从-6到-20
Root Delay:指示与主时钟参考源的总共往返延迟,以秒为单位,该字段只在服务器端有效。字段长度为32位浮点数,小数部分在16位以后,取值范围从负几毫秒到正几百毫秒
Root Dispersion:指示与主时钟参考源的误差,以秒为单位,该字段只在服务器端有效。字段长度为32位浮点数,小数部分在16位以后,取值范围从零毫秒到正几百毫秒
Reference Identifier:指示时钟参考源的标记,该字段只在服务器端有效。对于一级服务器,字段长度为4字节ASCII字符串,左对齐不足添零。对于二级服务器,在IPV4环境下,取值为一级服务器的IP地址,在IPV6环境下,是一级服务器的NSAP地址
Reference Timestamp:指示系统时钟最后一次校准的时间,该字段只在服务器端有效,以前面所述64位时间戳格式表示
Originate Timestamp:指示客户向服务器发起请求的时间,以前面所述64位时间戳格式表示
lReceive Timestamp:指服务器收到客户请求的时间 ,以前面所述64位时间戳格式表示。
Transmit Timestamp:指示服务器向客户发时间戳的时间,以前面所述64位时间戳格式表示
//Authenticator(可选):当需要进行SNTP认证时,该字段包含密钥和信息加密码
2. code结果测试验证
2.1 用wireshark抓到UE发出去的报文
UE只发了个Transmit timestamp这个时间戳给server
2.2 Server回复的SNTP报文
2.3 记录T1、T2、T3、T4各个时间点的数值
T1 = 1970.1.1 00:00:50.550999998
T2 = 2020.8.31 06:30:12.591166208 + 8h = 2020.8.31 14:30:12.591166208
T3 = 2020.8.31 06:30:12.591192346 + 8h = 2020.8.31 14:30:12.591192346
T4 = 根据tick得出ticks数值
然后 UE做打印,其公式为:T3 + [(T4-T1)-(T3-T2)] / 2,
整数数值:1598884212
毫秒数值:718953
该数值为基准时间,即获取tick那一刻,对应的绝对时间相对于1970.1.1 00:00:00过了1598884212s,718953ms
下面来分析下如何判断所的数值的正确性,注意:只能大致比较,因为100%正确的绝对时间是得不出来的,只能用上面的算法得出相对准确的时间进行同步。
网络单程时延:[(T4-T1)-(T3-T2)] / 2 = 127761ms
将T3的时间戳输入网页时间计算工具,得出的秒数差:1598884212.5,加上单程的网络时延,得到1598884212.718953,秒数的能从wireshark中得到验证,但毫秒数,由于计算得到的网络时延= 上行网络时延+下行网络时延,这里是将其两者看作等价的,所以直接除以2得到单程网络时延,所以在毫秒数值上有些许差异,很微小
开发中需注意点:
- 网络大端,UE小端的问题
- 得出UE与server之间时间差,还需+东八区8h时差,+UE开机的时间,再加上单程的网络时延,就是当前tick对应 北京标准时间 从1970.1.1 00:00:00所经过的时长数值
- 这段代码,按照最直接的思路:
4.在第一次获取ticks后,需要FRAC2USEC(tv.tv_usec)一下,再转成大端发给server,因为: 2^32 /10^6,表示sntp_transmit_timestamp.fracpart这里面,每1ms, frapart=2^32 /10^6
附加:Python代码
#/usr/local/bin/python3.5
#coding:utf-8import socket, struct, time
NTP_server = "0.uk.pool.ntp.org"
TIME1970 = 2208988800def sntp_client():client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)data = "\x1b" + 47 * "\0"client.sendto(data.encode('utf-8'), (NTP_server, 123))data, address = client.recvfrom(1024)if data:print("Response received from:", address)t = struct.unpack('!12I', data)[10]t -= TIME1970print('\tTime=%s' % time.ctime(t))sntp_client()
SNTP原理讲解 客户端 C语言实现相关推荐
- 实现原理讲解!2020Android目前最稳定和高效的UI适配方案!进阶学习资料!
前言 组件化是 保持整个 App 可持续地进行高质量开发的基础,近年来也是业界一直在积极探索和实践的方向,在深入理解组件化架构的过程中,将不断考验你的技术深度与广度: 实践中我还参考了十几家技术团队的 ...
- php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解
PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...
- nginx反向代理原理讲解
一 .概述 反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果 ...
- 用python画画的原理_matplotlib绘图的核心原理讲解
作者:朱小五 来自:凹凸数据(ID:alltodata) matplotlib是基于Python语言的开源项目,旨在为Python提供一个数据绘图包. 相信大家都用过它来数据可视化,之前我还分享过25 ...
- php 模板 原理,php模板原理讲解
php模板原理讲解 复制代码 代码如下: $data = array( 'title'=>'ilsea', 'list'=>array( 'hello', 'world' ) ); inc ...
- android源码学习-Toast实现原理讲解
前言: 前些日志QQ群有朋友发了一个Toast的崩溃日志.Toast如此简单的用法怎么会崩溃呢?所以顺便就学习了一下Toast在源码中的实现,不算复杂,但内容挺多的,这里就来分享一下,方便读者. 一. ...
- 【入门学习二】基于 FPGA 使用 Verilog 实现蜂鸣器响动的代码及原理讲解
目录 一.知识了解 二.模块设计 三.程序实现 四.管脚配置及结果展示 五.写给小白看的 上一篇博文:[入门学习一]基于 FPGA 使用 Verilog 实现按键点灯代码及原理讲解 功能描述:通过前面 ...
- 2021.1.4CHM文档制作(手动制作+软件制作+原理讲解)
目录 1.CHM文件起源及原理讲解 1.1起源 1.2特性 1.3原理 1.4技术要点 2.手动制作CHM 3.软件制作CHM 4.使用Python.C++.Java等语言无脑开发CHM制作工具 1. ...
- 微信小游戏开发教程-2D游戏原理讲解
微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...
最新文章
- html语言分行,Markdown内嵌Html语言
- C#: 旋转图片到正确位置
- 0130互联网新闻 | 小红书完成超3亿美元D轮融资;网易游戏收购Quantic Dream工作室少数股权...
- C# struct的陷阱:无法修改“...”的返回值,因为它不是变量
- 如何开启mysql计划事件
- 给窗口设置系统级或窗口级的热键
- iOS获取设备UUID和IDFA
- java 遍历arrayList的四种方法
- 【转】多态与 new [C#]
- android随机抽奖代码_随机抽奖生成器app下载|随机抽奖生成器软件下载_v1.0_9ht安卓下载...
- Go的全新漏洞检测工具govulncheck来了
- 如何使用 CSS 颜色?
- BERT源码embedding_lookup解析
- 微信小程序开发者工具运行不了
- ubuntu使用gdown下载谷歌云盘(google drive)文件
- Ubuntu 18.04 LTS 桌面版 WPS 安装字体
- python笔记更新(正则表达式)
- 数据库sql简单的优化方案
- “知识共享”扎根中国,前景无量
- Elasticsearch灾备同步方案功能验证(三)
热门文章
- 2021商洛中学高考成绩查询,商洛高中排名一览表
- c# 未能加载文件或程序集mysql.data,c# - 当我未引用文件或程序集Oracle.ManageddataAccess时,它无法加载 - 堆栈内存溢出...
- 就在20号!袋鼠云春季生长大会邀您共观数智生机,我们云上见
- 叫树兄的上海行849
- Docker Swarm安装(以ubuntu为例)
- acme.sh快速申请免费https证书
- 简易自制冰淇淋(本来想叫朗姆酒冰淇淋,酒好像挥发了)
- 清博大数据网络舆情监测\控软件功能作用与类似软件有哪些详解
- Game Of Life
- 华为近场通讯nfc在哪里打开_玩转手机NFC(近场通讯)标签