zoukankan      html  css  js  c++  java
  • Java获取NTP网络时间

     最近项目中涉及到一个时间验证的问题,需要根据当前时间来验证业务数据是否过期。所以直接写代码如下:

             new java.util.Date().getTime();  
            结果测试的时候出现了问题,怎么验证都是过期。后来发现是服务器主机时间不对。也就是说如果服务器时间不准确或者被篡改,那么验证这部分会出现问题。所以决定采用获取网络当前时间来代替获取系统当前时间
            搜索了一下,原来获取网络时间有一个协议:Network Time Protocol(NTP: 网络时间协议 )。 
            协议有了,那么java有没有相关实现呢。当然也有了。apache的commons-net包下面有ntp的实现。主要的类是: 

                  org.apache.commons.net.ntp.NTPUDPClient               org.apache.commons.net.ntp.TimeInfo 
    看下用法,NTPUDPClient中有方法: 
            public TimeInfo getTime(InetAddress host, int port) throws IOException 

              public TimeInfo getTime(InetAddress host) throws IOException 


    第二个重载方法是用协议规范默认端口:123。 

    看下具体实现代码: 

    /***
         * Retrieves the time information from the specified server and port and
         * returns it. The time is the number of miliiseconds since
         * 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305.
         * This method reads the raw NTP packet and constructs a <i>TimeInfo</i>
         * object that allows access to all the fields of the NTP message header.
         * <p>
         * @param host The address of the server.
         * @param port The port of the service.
         * @return The time value retrieved from the server.
         * @exception IOException If an error occurs while retrieving the time.
         ***/
        public TimeInfo getTime(InetAddress host, int port) throws IOException
        {
            // if not connected then open to next available UDP port
            if (!isOpen())
            {
                open();
            }
    
            NtpV3Packet message = new NtpV3Impl();
            message.setMode(NtpV3Packet.MODE_CLIENT);
            message.setVersion(_version);
            DatagramPacket sendPacket = message.getDatagramPacket();
            sendPacket.setAddress(host);
            sendPacket.setPort(port);
    
            NtpV3Packet recMessage = new NtpV3Impl();
            DatagramPacket receivePacket = recMessage.getDatagramPacket();
    
            /*
             * Must minimize the time between getting the current time,
             * timestamping the packet, and sending it out which
             * introduces an error in the delay time.
             * No extraneous logging and initializations here !!!
             */
            TimeStamp now = TimeStamp.getCurrentTime();
    
            // Note that if you do not set the transmit time field then originating time
            // in server response is all 0's which is "Thu Feb 07 01:28:16 EST 2036".
            message.setTransmitTime(now);
    
            _socket_.send(sendPacket);
            _socket_.receive(receivePacket);
    
            long returnTime = System.currentTimeMillis();
            // create TimeInfo message container but don't pre-compute the details yet
            TimeInfo info = new TimeInfo(recMessage, returnTime, false);
    
            return info;
        }
    

    大概过程就是想目标网络地址发包来获取网络时间,具体细节由协议来规范。 
    所以我们还需要来确定网络地址,继续搜索,发现网络上有时间服务器,也叫授时服务器。我们的用智能手机的时间是不是通过这种方式来同步的呢? 
           找到了这样一些服务器地址: 
    中国时间网 
           国外的 
    NIST Internet Time Servers 

    代码例子: 

    	public static void main(String[] args) {
    		try {
    			NTPUDPClient timeClient = new NTPUDPClient();
    			String timeServerUrl = "time-a.nist.gov";
    			InetAddress timeServerAddress = InetAddress.getByName(timeServerUrl);
    			TimeInfo timeInfo = timeClient.getTime(timeServerAddress);
    			TimeStamp timeStamp = timeInfo.getMessage().getTransmitTimeStamp();
    			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    			System.out.println(dateFormat.format(timeStamp.getDate()));
    		} catch (UnknownHostException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    

      输出:2013-04-0211:01:08  

  • 相关阅读:
    学生管理
    数据类型
    Linux安装、发布Django项目
    函数式编程
    学生管理系统
    mysql数据库工具类
    python操作数据库
    链接mysql建库建表
    列表元组字典集合
    内置对象相关方法
  • 原文地址:https://www.cnblogs.com/arnoid/p/3208809.html
Copyright © 2011-2022 走看看