使用TimeTCPClient从公共时间服务器获取时间

时间:2011-08-16 16:06:37

标签: java ntp

我尝试使用以下代码从公共时间服务器获取时间。

package aaa;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.net.TimeTCPClient;

public final class Main
{
    public static java.util.Date getNTPDate() {
        List<String> hosts = Arrays.asList("0.pool.ntp.org");

        for (String host : hosts) {
            TimeTCPClient client = new TimeTCPClient();
            // We want to timeout if a response takes longer than 5 seconds
            client.setDefaultTimeout(5000);
            try {
                client.connect(host);
                java.util.Date ntpDate = client.getDate();
                client.disconnect();
                // Just to be extra caution.
                if (ntpDate != null) {
                    return ntpDate;
                }
            }
            catch (java.net.SocketException exp) {
                exp.printStackTrace();
            }
            catch (java.io.IOException exp) {
                exp.printStackTrace();
            }
        }
        return null;
    }

    public static final void main(String[] args)
    {
        System.out.println(getNTPDate());
    }

}

但是,我一直在java.net.ConnectException: Connection timed out: connect

我曾尝试谷歌几个不同的时间服务器。但是,他们没有工作。我想知道,问题出在我的代码或我选择的服务器上吗?

4 个答案:

答案 0 :(得分:10)

NTP是一种与时间协议不同的协议。 NTP服务器仅通过端口UDP / 123进行通信。时间服务器使用TCP / 37(TimeTCPClient似乎正确实现)。

如果您想获得远程时间,请使用合适的服务器( ntp.xs4all.nl 似乎正在侦听时间端口)。

答案 1 :(得分:7)

您可以使用正确的方法:

import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;

import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;

public final class PublicServerTime {

    public static Date getNTPDate() {

        String[] hosts = new String[]{
            "ntp02.oal.ul.pt", "ntp04.oal.ul.pt",
            "ntp.xs4all.nl"};

        NTPUDPClient client = new NTPUDPClient();
        // We want to timeout if a response takes longer than 5 seconds
        client.setDefaultTimeout(5000);

        for (String host : hosts) {

            try {
                InetAddress hostAddr = InetAddress.getByName(host);
                System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress());
                TimeInfo info = client.getTime(hostAddr);
                Date date = new Date(info.getReturnTime());
                return date;

            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }

        client.close();

        return null;

    }


    public static final void main(String[] args) {

        System.out.println(getNTPDate());

    }

答案 2 :(得分:0)

好吧,我可以从我的机器上ping服务器0.pool.ntp.org,是吗?由于超时异常主要是由于运行此代码的机器无法在60秒内连接到主机。

答案 3 :(得分:0)

public class NTPService {

    private final static Logger logger = Logger.getLogger(NTPService.class);
    private final static int TIMEOUT = 5000;
    private final static List<String> hostList = 
                                   Arrays.asList("time.windows.com", "nl.pool.ntp.org");

    private final NTPUDPClient client = new NTPUDPClient();

    public NTPService() {
        client.setDefaultTimeout(TIMEOUT);
    }

    public LocalDateTime getNTPDateTime() {
        for (final String host : hostList) {
            final LocalDateTime localDateTime = getNTPDateTime(host);
            if (null != localDateTime) {
                return localDateTime;
            }
        }
        return null;
    }

    private LocalDateTime getNTPDateTime(final String host) {
        try {
            client.open();
            return convertToLocalDateTime(
                    TimeStamp.getNtpTime(client.getTime(InetAddress.getByName(host))
                                  .getReturnTime()).getTime());
        } catch (final Exception exp) {
            logger.warn(String.format("%s: failed to update NTP", host), exp);
            return null;
        } finally {
            if (client.isOpen()) {
                client.close();
            }
        }
    }

    private LocalDateTime convertToLocalDateTime(final long value) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(value),
               ZoneId.systemDefault());
    }
}

用法:

System.out.println(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss").
                   format(new NTPService().getNTPDateTime()));