时间记录:2019-9-30
最近在进行时间戳的服务的阅读的时候发现了我们通常会使用一个公用的时间源作为一个标准的时间,我们知道在windows中有一个网络时间同步的功能那里使用的同步的时间源就是基于一种协议的网络的时间的请求。通常在作为网络的时间机器的时间的依据是一个量子时间钟,这个时间的误差在2000万年的误差很小。我们不做研究在这里,我们这里主要了解下时间的网络的协议的格式以及数据的传输的方式,在进行获取网络时间的时候如何进行网络的时间的获取(这里以java的方式来进行请求)
我们首先建立自己的时间源服务,这里使用的是ntp,然后就是不同版本的rfc的协议的格式,然后就是在java下如何进行时间的获取(其实只要了解其的网络的协议的格式就可以了,不仅仅是局限于语言)
搭建自己的时间源
环境描述:我这里是基于虚拟机的操作
安装
yum install ntp
配置ntp
vi /etc/ntp.conf
找到service,添加自己的地址127.0.0.1,将其余的上游注释,也可以使用其余上游
我们只需要指定当前的时间源为服务的时间源,在实际的环境中通常会有多级的时间源,这里也可以进行简单的配置
时间源服务的默认端口为123
时间源的数据格式
时间源服务的协议的报文格式服从RFC标准
从下面的NtpMessage中有得知支持所有版本的NTP和SNTP
This class represents a NTP message, as specified in RFC 2030. The message format is compatible with all versions of NTP and SNTP.
协议介绍这一块不做具体的研究了,平时使用的不多,主要记录下,存在这样一个东西
java的时间数据的获取
sntp使用的是UDP的网络协议,进行数据的传输,在java中封装组合了UDP协议的DatagramSocket的api进行网络的请求。然后我们需要知道对应的网络协议的数据格式,就可以进行数据的交互,将对应的数据格式转换为自己需要的,可以理解的数据,实际上就是对一对的数据进行持久化的封装,以供自己的需求和使用,java中有现成的javasntpclient.源地址链接,我们尝试使用此项进行网络的时间源的数据的获取。其中主要的是NtpMessage的封装,为了跟方便的使用
package com.huo.time;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.DecimalFormat;
/**
* NtpClient - an NTP client for Java. This program connects to an NTP server
* and prints the response to the console.
*
* The local clock offset calculation is implemented according to the SNTP
* algorithm specified in RFC 2030.
*
* Note that on windows platforms, the curent time-of-day timestamp is limited
* to an resolution of 10ms and adversely affects the accuracy of the results.
*
*
* This code is copyright (c) Adam Buckley 2004
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version. A HTML version of the GNU General Public License can be
* seen at http://www.gnu.org/licenses/gpl.html
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* @author Adam Buckley
*/
public class SntpClient
{
public static void main(String[] args) throws IOException
{
String serverName = "192.168.195.128";
// Process command-line args
// if(args.length==1)
// {
// serverName = args[0];
// }
// else
// {
// printUsage();
// return;
// }
// Send request
DatagramSocket socket = new DatagramSocket();
InetAddress address = InetAddress.getByName(serverName);
byte[] buf = new NtpMessage().toByteArray();
DatagramPacket packet =
new DatagramPacket(buf, buf.length, address, 123);
// Set the transmit timestamp *just* before sending the packet
// ToDo: Does this actually improve performance or not?
NtpMessage.encodeTimestamp(packet.getData(), 40,
(System.currentTimeMillis()/1000.0) + 2208988800.0);
socket.send(packet);
// Get response
System.out.println("NTP request sent, waiting for response...\n");
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// Immediately record the incoming timestamp
double destinationTimestamp =
(System.currentTimeMillis()/1000.0) + 2208988800.0;
// Process response
NtpMessage msg = new NtpMessage(packet.getData());
// Corrected, according to RFC2030 errata
double roundTripDelay = (destinationTimestamp-msg.originateTimestamp) -
(msg.transmitTimestamp-msg.receiveTimestamp);
double localClockOffset =
((msg.receiveTimestamp - msg.originateTimestamp) +
(msg.transmitTimestamp - destinationTimestamp)) / 2;
// Display response
System.out.println("NTP server: " + serverName);
System.out.println(msg.toString());
System.out.println("Dest. timestamp: " +
NtpMessage.timestampToString(destinationTimestamp));
System.out.println("Round-trip delay: " +
new DecimalFormat("0.00").format(roundTripDelay*1000) + " ms");
System.out.println("Local clock offset: " +
new DecimalFormat("0.00").format(localClockOffset*1000) + " ms");
socket.close();
}
/**
* Prints usage
*/
static void printUsage()
{
System.out.println(
"NtpClient - an NTP client for Java.\n" +
"\n" +
"This program connects to an NTP server and prints the response to the console.\n" +
"\n" +
"\n" +
"Usage: java NtpClient server\n" +
"\n" +
"\n" +
"This program is copyright (c) Adam Buckley 2004 and distributed