Skip to content

zyywbx/ntp-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

目录

第 1 章 NTP 原理

1.1.NTP用途

NTP(Network Time Protocol,网络时间协议)是用来使网络中的各个计算机时间同步的一种协议。它的用途是把计算机的时钟同步到世界协调时UTC,其精度在局域网内可达0.1ms,在互联网上绝大多数的地方其精度可以达到1-50ms。

它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)进行时间同步,它可以提供高精准度的时间校正,而且可以使用加密确认的方式来防止病毒的协议攻击。

1.2 NTP原理

NTP要提供准确的时间,就必须有准确的时间来源,那可以用格林尼治时间吗?答案是否定的。因为格林尼治时间是以地球自转为基础的时间计量系统,但是地球每天的自转是有些不规则的,而且正在缓慢加速,因此,格林尼治时间已经不再被作为标准时间使用。

新的标准时间,是由原子钟报时的国际标准时间UTC(Universal Time Coordinated,世界协调时)。所以NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。有了准确而可靠的的时间源,那这个时间如何传播呢?在NTP中,定义了时间按照服务器的等级传播,按照离外部UTC源远近将所有的服务器归入不同的Stratum(层)中,例如把通过GPS(Global Positioning System,全球定位系统)取得发送标准时间的服务器叫Stratum-1的NTP服务器,而Stratum-2则从Stratum-1获取时间,Stratum-3从Stratum-2获取时间,以此类推,但Stratum层的总数限制在15以内。所有这些服务器在逻辑上形成阶梯式的架构相互连接,而Stratum-1的时间服务器是整个系统的基础

NTP时间同步报文中包含的时间是格林威治时间,是从1900年开始计算的秒数

1.3 NTP报文格式

NTP有两种不同类型的报文,一种是时钟同步报文,另一种是控制报文。控制报文仅用于需要网络管理的场合,它对于时钟同步功能来说并不是必需的,这里不做介绍。

LI VN Mode Stratum Poll Precision
0-2bit 3-5bit 6-8bit 9-16bit 17-24bit 25-32bit
Root Delay 32bit
Root Dispersion 32bit
Reference Timestamp 64bit
Originate Timestamp 64bit
Receive Timestamp 64bit
Transmit Timestamp 64bit
Authentication (optional) 64bit
字段中文名 字段英文名 值定义
闰秒提示符 LI 0 无预告1 最近一分钟有61秒2 最近一分钟有 59秒3 警告状态(时钟未同步)
版本号 VN 这是一个三位的整数可以用于表示NTP版本最新版本为4
模式 Mode 0 保留 1 对称主动 2 对称被动 3 客户端 4 服务器端 5 广播 6 为NTP控制控制消息 7 为自用保留
本地时钟层级 Stratum 0 未定义或难以获得 1 主要参考(如无线电时钟钟,校正的原子时钟) 2-255 第二参考(通过NTP或SNTP)
轮询间隔 Poll 这是一个8位有符号整数,用于表示连续消息之间的最大间隔,以最接近2的N次幂来表示。如值为6表示2^6=64。
本地时钟经度 Precision 这是一个8位有符号整数,用于表示本地时钟精度,以最接近2的N次幂来表示。
根延迟 Root delay 这是一个32位有符号定点数,表示主要参考源的总往返时延,以秒为单位。该变量可以为正值和负值,具体取决于时间精度和偏移。
最大误差偏移 Root Dispersion 这是一个32位有符号定点数,表示相对于主参考源的最大误差,以秒为单位,在15和16位之间。通常在该字段中出现的值范围为0到几百毫秒
标识特定参考源位串 Reference Identifier 一个标识特定参考源的32位位串。在NTP版本3或版本4层级0或层级1服务器的情况下,这是一个4字符ASCII字符串,左对齐并且以0填充到32位。在NTP版本3辅助服务器中,这是参考源的32位IPv4地址。
上次设置或更正的本地时间戳 Reference Timestamp 这是以64位时间戳格式表示的上次设置或更正的本地时钟时间。
时间报文离开本地客户端的时间戳 Original Timestamp 这是以64位时间戳格式表示的请求离开客户端的时间。
请求到达服务器的时间戳 Receive Timestamp 这是以64位时间戳格式表示的请求到达服务器端的时间。
应答离开服务器的时间戳 Transmit Timestamp 这是以64位时间戳格式表示的应答离开服务器端的时间。
认证信息 Authentication 认证信息。

​ 表1-1 NTP报文英文字段及其中文解释

第 2 章NTP模块的设计

2.1 NTP模块运行的大体流程图

开始=》构造NTP报文=》向服务器发送报文=》监听服务器的报文回复=》接收服务器的回复=》处理服务器发来的报文并且更新系统时间=》结束

NTP抓取时间的模块的大概流程思路如上所示。

  1. 构造向服务器发送的NTP报文

  2. 创建并配置要向服务器发送报文的socket(套接字),使用sockaddr_in结构体配置socket。配置完成之后使用connect函数,建立socket与服务器的连接。建立连接成功之后使用send函数通过socket将其中的报文发送给服务器。

  3. 将套接字加入到一个fd_set之中然后使用,select函数对其状态进行监听。

  4. 检测到可读事件后,select函数会返回一个特定的返回值,之后调用recv函数对服务器返回的报文进行接收。

  5. 成功接收到服务器返回的报文并确认其无误之后,对报文进行解析处理。获得了从服务器获得的时间之后,更新系统的时间完成整个流程。

    注:在该模块中,发送一次报文回得来一次服务器的报文回复,所以整个流程需要做成一次性的处理,如果中间的流程出现错误,可以直接退出循环的流程直接开始下一次。

在该模块中中,将NTP报文的构造,以及报文的发送封装进了send_packet函数。

将接收服务器发来的报文,以及将报文解析的工作封装进了get_server_time中。

将更新系统时间封装进了mod_localtime函数之中。

其他的一些准备工作例如一些变量的声明及初始化,socket的创建,连接服务器connect,监听select,写在了ntp_get_time_run主流程之中。

2.2 异常处理

异常处理部分将整个流程封装成了一个ntp_get_time_run中,如果同一个错误出现五次,那么调用回调函数向调用者返回一个整形的错误代码 -1.

2.3 接口

NTP时间获取模块的API函数提供了了两个接口。

表头文件 #include “ntp_time”
定义函数 int ntp_get_time(void(*ntpCall),int)
函数说明 其中第一个参数为调用者提供了回调函数的接口,调用者可以通过将自己的方法函数,获得NTP模块的工作状况,返回一个int 型的整数,其中获取时间失败为-1,成功获取时间为1.。int in_tryTime为调用者提供了一个能够控制NTP模块运行次数的接口,调用者可以通过设定int型次数,控制NTP模块的运行次数,如果输入0则模块不会结束,以一定时间一直更新系统的时间。
返回值 调用成功返回0,出现错误返回-1

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages