以下程序执行DNS查找。除了主机名和dns的一个特定组合之外,它的效果很好:
import javax.naming.directory.InitialDirContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public final class StackOverflow {
public static void main(String args[]) throws NamingException {
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url", "dns://ns.dnssek.org");
System.out.println(new InitialDirContext(env).getAttributes("dnsseccert.us", new String[]{"NS","A"}));
}
}
我试图设置超时:
env.put("com.sun.jndi.dns.timeout.initial", "220");
然而它表现得很奇怪。当它抛出时,它有时适用于小值:
DNS error [Root exception is java.net.SocketTimeoutException: Receive timed out];
但是大多数时候程序只是冻结并挂起在内存中。
让其他人遇到同样的问题并解决了吗?有没有其他设置我可以尝试阻止它?还有其他的替代 java.naming.factory.initial 我可以试试吗?
答案 0 :(得分:3)
花了我几个小时,但我终于找到了一个可以接受的解决方案。我下载了包 com.sun.jndi.dns 的源代码,并在类 DnsClient 中添加了一行:
...
Tcp(InetAddress server, int port, int timeout) throws IOException {
sock = new Socket(server, port);
sock.setSoTimeout(timeout); // <-- missing timeout
sock.setTcpNoDelay(true);
out = new java.io.BufferedOutputStream(sock.getOutputStream());
in = new java.io.BufferedInputStream(sock.getInputStream());
}
...
我设置套接字的timout。我实际上还在Tcp构造函数中添加了一个参数并修改了它的调用,因此它现在由 com.sun.jndi.dns.timeout.initial 中的值初始化。
答案 1 :(得分:0)
请尝试同时设置com.sun.jndi.dns.timeout.initial
和com.sun.jndi.dns.timeout.retries
的值。例如,我看到与以下内容一致的超时:
$ cat StackOverflow.java
import javax.naming.directory.InitialDirContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public final class StackOverflow {
public static void main(String args[]) throws NamingException {
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url", "dns://ns.dnssek.org");
env.put("com.sun.jndi.dns.timeout.initial", "220");
env.put("com.sun.jndi.dns.timeout.retries", "1");
System.out.println(new InitialDirContext(env).getAttributes("dnsseccert.us", new String[]{"NS","A"}));
}
}
$ java -version
java version "11" 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11+28)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11+28, mixed mode)
$ java StackOverflow
Exception in thread "main" javax.naming.CommunicationException: DNS error [Root exception is java.net.SocketTimeoutException: Receive timed out]; remaining name 'dnsseccert.us'
at jdk.naming.dns/com.sun.jndi.dns.DnsClient.query(DnsClient.java:313)
at jdk.naming.dns/com.sun.jndi.dns.Resolver.query(Resolver.java:81)
at jdk.naming.dns/com.sun.jndi.dns.DnsContext.c_getAttributes(DnsContext.java:434)
at java.naming/com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:235)
at java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:141)
at java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:129)
at java.naming/javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:142)
at StackOverflow.main(StackOverflow.java:14)
Caused by: java.net.SocketTimeoutException: Receive timed out
at java.base/java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.base/java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:181)
at java.base/java.net.DatagramSocket.receive(DatagramSocket.java:814)
at jdk.naming.dns/com.sun.jndi.dns.DnsClient.doUdpQuery(DnsClient.java:423)
at jdk.naming.dns/com.sun.jndi.dns.DnsClient.query(DnsClient.java:212)
... 7 more
您当然要配置在您自己的环境中有意义的超时和重试值。以上数值仅供参考。