Java быстро проверяет сетевое подключение

моя проблема довольно проста. Моя программа требует немедленного уведомления, если сетевое соединение потеряно. Я использую Java 5, поэтому я не могу использовать очень удобные функции NetworkInterface.

В настоящее время у меня есть два разных метода проверки сетевого подключения:
(пытаться..уловы удалены)

Способ Один:

URL url = new URL("http://www.google.com");
HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
// trying to retrieve data from the source. If offline, this line will fail:
Object objData = urlConnect.getContent();
return true;

Способ 2:

Socket socket = new Socket("www.google.com", 80);
netAccess = socket.isConnected();
socket.close();
return netAccess;

однако оба этих метода блокируются до a Времени ожидания перед возвратом значения false. Мне нужен метод, который вернется немедленно, но совместим с Java 5.

спасибо!

изменить: Я забыл упомянуть, что моя программа зависит от IP-адресов, а не DNS-имен. Таким образом, проверка на наличие ошибки при разрешении хоста отсутствует...

2-е изд:

выяснил окончательное решение, используя NetworkInterface:

Enumeration<NetworkInterface> eni = NetworkInterface.getNetworkInterfaces();
        while(eni.hasMoreElements()) {
            Enumeration<InetAddress> eia = eni.nextElement().getInetAddresses();
            while(eia.hasMoreElements()) {
                InetAddress ia = eia.nextElement();
                if (!ia.isAnyLocalAddress() && !ia.isLoopbackAddress() && !ia.isSiteLocalAddress()) {
                    if (!ia.getHostName().equals(ia.getHostAddress()))
                        return true;
                }
            }
        }

4 ответов


От JGuru

начиная с Java 5, существует метод isReachable() в Класс InetAddress. Можно указать тайм-аут или Сетевом интерфейсе для использования. Дополнительные сведения о базовых Протокол сообщений управления интернетом (ICMP), используемый ping, см. RFC 792 (http://www.faqs.org/rfcs/rfc792.html).

использование из Java2s

  int timeout = 2000;
  InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
  for (InetAddress address : addresses) {
    if (address.isReachable(timeout))
      System.out.printf("%s is reachable%n", address);
    else
      System.out.printf("%s could not be contacted%n", address);
  }

Если вы хотите избежать блокировки, используйте Java NIO (неблокирующий IO) на Яве.пакет НИО

String host = ...; 
InetSocketAddress socketAddress = new InetSocketAddress(host, 80); 
channel = SocketChannel.open(); 
channel.configureBlocking(false); 
channel.connect(socketAddress);

моя программа требует немедленного уведомления, если сетевое подключение потерянный.

невезение. Вы не можете получить немедленное уведомление с TCP/IP. Он полон буферизации, повторных попыток и тайм-аутов, поэтому он не делает что-нибудь немедленно, и TCP по дизайну не имеет ничего, соответствующего "тону набора", ни какого-либо API. Единственный способ обнаружить потерянное соединение-попытаться сделать ввод-вывод над ним.

Я использую Java 5, поэтому Я не могу использовать очень удобные функции Сетевом интерфейсе.

они вам тоже не помогут. Все, что они могут сказать вам, - это вверх или вниз, ничего о состоянии вашей связи с широким миром.

URL url = new URL("http://www.google.com");
HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
// trying to retrieve data from the source. If offline, this line will fail:
Object objData = urlConnect.getContent();
return true;

это будет тайм-аут с сбоем DNS, если вы находитесь в автономном режиме.

Socket socket = new Socket("www.google.com", 80);
netAccess = socket.isConnected();
socket.close();
return netAccess;

Дитто. Однако даже если это не так, гнездо.isConnected () всегда будет возвращать true. Эти API, такие как isConnected(), isBound(), isClosed (), только говорят вам что?!--7-->вы на гнездо. они ничего не говорят вам о состоянии подключение. они не могут, по причине, которую я дал выше.

и вы забыли закрыть сокет в случае исключения, поэтому у вас есть утечка ресурсов.

мне нужен метод, который вернется немедленно.

невозможно по указанным причинам. Вам нужно перепроектировать вокруг реализации этой функции не существует.


вам нужно сначала создать interface под названием NetworkListener, например

public interface NetworkListener {
    public void sendNetworkStatus(String status);
}

затем создайте класс и назовите его NetworkStatusThread, например

public class NetworkStatusThread implements Runnable {
    List listenerList = new Vector();

    @SuppressWarnings("unchecked")
    public synchronized void addNetworkListener(NetworkListener nl) {
        listenerList.add(nl);
    }

    public synchronized void removeNetworkListener(NetworkListener nl) {
        listenerList.remove(nl);
    }


    private synchronized void sendNetworkStatus(String status) {
        // send it to subscribers
        @SuppressWarnings("rawtypes")
        ListIterator iterator = listenerList.listIterator();
        while (iterator.hasNext()) {
            NetworkListener rl = (NetworkListener)iterator.next();
            rl.sendNetworkStatus(status);
        }
    }

    public void run() {
        while (true) {
        System.out.println("Getting resource status");
        try {
             Thread.sleep(2000);
             System.out.println("Sending resource status to registered listeners");
             this.sendResourceStatus("OK");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 }

тогда в вашем классе, который создает экземпляр Thread сделайте так:

NetworkStatusThread netStatus = new NetworkStatusThread();
netStatus.addNetworkListener(this);
Thread t = new Thread(netStatus);
t.Start();

кроме того, в этом классе вам нужно implement на NetworkListener, чтобы получить обратные вызовы.

в своем run() метод выше, вы можете реализовать код @Ali, но передать мой статус:

  int timeout = 2000;
  InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
  for (InetAddress address : addresses) {
    if (address.isReachable(timeout))
       this.sendResourceStatus("OK");
    else
       this.sendResourceStatus("BAD");
  }

вы пытались выдать разрешение DNS?

вы можете попробовать с:

public static InetAddress[] getAllByName(String host)

но я не уверен, что для этого потребуется тайм-аут..