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  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM