创建时间: 2017-09-11
最后修改时间: 2017-09-11因个人水平有限,文章中存在不足,错误之处,还望指正
实验环境
Linux 2.6.32
gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
引言
本NTP客户端实现是基于NTPv3单播模式来实现的,其中参考了SNTP的实现(SNTP为NTP的简化版)。
要完成客户端的开发需要准备一些知识,比如NTP工作模式,NTP报文格式等等,大体了解完这些后才能更好地掌握整个开发过程。
NTP协议
简介
NTP(Network Time Protocol),网络时间协议,应用于分布式时间服务器和客户端之间,实现客户端和服务器之间的时间同步,从而使网络内所有设备的时间基本保持一致。NTP工作于UDP的123端口。
NTP报文格式
0 2 5 8 16 24 32
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Reference Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Originate Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Receive Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transmit Timestamp (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Authentication (optional) (64) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NTPv3报文格式
Leap Indicator(LI)
闰秒指示符,这是一个2位的代码,用于警示在当天的最后一分钟里插入或删除的闰秒。取值如下:0 无预告 1 最近一分钟有61秒 2 最近一分钟有59秒 3 警告状态(时钟未同步)
Version Number(VN)
版本号,这是一个3位的整数,用于表示NTP的版本。Mode
模式,这是一个3位的整数,表示模式,值定义如下: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
认证信息。
NTP时间戳
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Integer Part |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Fraction Part |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
NTP时间戳格式
NTP时间戳使用的是自1970-01-01所经过的秒数(单位为秒),它分为整数部分和小数部分。NTP时间戳整数部分与ICMP时间戳消息所使用的时间戳格式整数部分一致,但小数部分却是不同的。
在64位的NTP时间戳中,前32位为整数部分,后32位为小数部分,其转换如下:
frac * 1e6 / (2<<32)
= frac / 4294.