Check Host alive + DNS Timeout

sebastianb

Erfahrenes Mitglied
Hallo zusammen,

ich schreibe gerade ein kleines Diagnose-Tool mithilfe dessen ich u.a. überprüfen will ob bestimmte Hosts innerhalb eines gewissen Schwellwertes erreichbar sind:

Java:
boolean alive = InetAddress.getByName("www.heise.de").isReachable(1000)

Eigentlich ja kein Hexenwerk - bekomme ich innerhalb von 1000ms kein Response ist alive = false.
Mein Problem ist nun, das wenn der Hostname nicht aufgelöst werden kann das Programm für rund 10s steht und dann erst eine UnknownHostException wirft.
Kenn jemand von euch eine Möglichkeit für die getbyName-Methode einen Timeout zu definieren oder eine andere Möglichkeit einen Hostname aufzulösen?

Viele Grüße

Sebastian
 
Hi,

hab nur ein ähnliches Problem gefunden, eventuell kannst du das wie in folgendem Bugreport beschrieben auch für dich brauchen: Bug #4630910

(Ungetestet, Probiers einfach mal aus :))

Gruß
BK
 
Hey,

danke für den Tipp. Die Lösung sieht zwar echt gut aus, funktionier aber leider nicht :/

Java:
System.setProperty("com.sun.jndi.dns.timeout.initial", "500"); // Keine Auswirkung
System.setProperty("com.sun.jndi.dns.timeout.retries", "1"); // Keine Auswirkung

long before = System.currentTimeMillis();
InetAddress host = Inet4Address.getByName("www.google.deXX");
System.out.println(System.currentTimeMillis() - before);
System.out.println(host.isReachable(1000));

Gruß

Sebastian
 
Versuche diese Parameter mal mit
Code:
java -Dcom.sun.jndi.dns.timeout.initial=500 ... usw
dierekt der VM zu übergeben und nicht wärend der Runtime zu setzen ...
 
Hey Spike,

danke für den Tipp aber leider hatte diese Änderung auch keinerlei Effekt auf die Namensauflösung.

Ich habe hier nun eine extremst hässliche Methode um die Namensauflösung nach einem vorgegebenen Timeout zu unterbrechen:



Java:
public InetAddress resolveHostname(final String hostname, final int timeout)
	{
		final Object token = new Object();

		List<InetAddress> list = new ArrayList<InetAddress>(1);

		class Resolver implements Runnable
		{
			private List<InetAddress> list;

			public Resolver(List<InetAddress> list)
			{
				this.list = list;
			}

			@Override
			public void run()
			{
				try
				{
					list.add(Inet4Address.getByName(hostname));
				}
				catch (UnknownHostException e)
				{
					// Ignore
				}

				synchronized (token)
				{
					token.notify();
				}
			}
		}

		new Thread(new Resolver(list)).start();

		synchronized (token)
		{
			try
			{
				token.wait(timeout);
			}
			catch (InterruptedException e)
			{
				// Ignore
			}
		}
		return (list.size() == 1) ? list.get(0) : null;
	}

	public static void main(String[] args) throws Exception
	{
		InetAddress host = new TestClass().resolveHostname("www.google.de", 50);
		System.out.println(host);
	}
Naja könnte man getByName interrupten, wär vieles einfacher...


Hier noch ein paar Sonderheiten:

F: Warum eine innere Klasse und nicht eine anonyme Klasse (new Runnable(){...}) ?
A: Eine Anonyme Klasse kann keinen Parameterbehafteten Konstruktor enthalten

F: Warum wird die InetAddress (host) in ein ArrayList gepackt?
A: Das wüsste ich auch gerne aber wenn ich dem Konstruktor direkt ein InetAddress übergebe und dieses dann in der Run-Methode setze ist es nach der Ausführung in der äußeren Methode immer null Oo. In einer ArrayList verpackt gehts aber? WTF?

F: Warum so hässlich?
A: Kein Nerv mehr :D
 
Zuletzt bearbeitet:
So ich habs eben aus Spaß nochmal getestet und jetzt gehts auch so:

Java:
public InetAddress resolveHostname(final String hostname, final int timeout)
	{
		final Object token = new Object();

		InetAddress[] host = new InetAddress[1];

		class Resolver implements Runnable
		{
			private InetAddress[] host;

			public Resolver(InetAddress[] host)
			{
				this.host = host;
			}

			@Override
			public void run()
			{
				try
				{
					host[0] = Inet4Address.getByName(hostname);
				}
				catch (UnknownHostException e)
				{
					// Ignore
				}

				synchronized (token)
				{
					token.notify();
				}
			}
		}

		new Thread(new Resolver(host)).start();

		synchronized (token)
		{
			try
			{
				token.wait(timeout);
			}
			catch (InterruptedException e)
			{
				// Ignore
			}
		}
		return host[0];
	}

	public static void main(String[] args) throws Exception
	{
		InetAddress host = new TestClass().resolveHostname("www.google.de", 10);
		System.out.println(host);
	}

Falls jemand eine bessere Lösung kennt, darf er mir die gerne mitteilen :)

Gruß Sebastian
 

Neue Beiträge

Zurück