2011-08-09 52 views
10

Vấn đề của tôi khá đơn giản. Chương trình của tôi yêu cầu thông báo ngay lập tức nếu kết nối mạng bị mất. Tôi đang sử dụng Java 5, vì vậy tôi không thể sử dụng các tính năng rất tiện dụng của NetworkInterface.Java Kiểm tra nhanh kết nối mạng

Hiện nay tôi có hai phương pháp khác nhau của việc kiểm tra kết nối mạng:
(try..catches loại bỏ)

Một phương pháp:

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; 

Cách 2:

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

Tuy nhiên, cả hai phương pháp này đều chặn cho đến khi hết thời gian chờ trước khi trả về false. Tôi cần một phương thức sẽ trả về ngay lập tức, nhưng tương thích với Java 5.

Cảm ơn!

EDIT: Tôi quên đề cập rằng chương trình của tôi phụ thuộc vào địa chỉ IP, không phải tên DNS. Vì vậy, việc kiểm tra lỗi khi giải quyết một loạt là ra ...

EDIT 2:

đặn ra một giải pháp cuối cùng sử dụng 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; 
       } 
      } 
     } 
+0

Tôi không quen thuộc với Java, nhưng tôi nghĩ rằng 'http: //' trong phương pháp 2 là quá nhiều. – glglgl

+0

Bạn có thể sử dụng Java 5.0 để chạy một ứng dụng Java 6 hoặc 7 có thể sử dụng NetworkInterface.;) –

+0

có vẻ như bạn cần một phương thức gọi lại để thông báo cho bạn khi có điều gì đó thay đổi trong trạng thái mạng. –

Trả lời

10

Từ JGuru

Bắt đầu với Java 5, có một phương thức isReachable() trong lớp InetAddress. Bạn có thể chỉ định thời gian chờ hoặc NetworkInterface để sử dụng. Để biết thêm thông tin về Giao thức Thư Điều khiển Internet (ICMP) cơ bản được sử dụng bởi ping, hãy xem RFC 792 (http://www.faqs.org/rfcs/rfc792.html).

Cách sử dụng từ 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); 
    } 

Nếu bạn muốn tránh chặn sử dụng Java NIO (Non-blocking IO) trong gói java.nio

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

Rất tiếc, phương pháp này sẽ vẫn chặn cho đến khi hết thời gian chờ. Thậm chí tệ hơn, nó sẽ chặn cho mỗi InetAddress trong mảng. Cảm ơn mặc dù. – BenCole

+0

Hmmm ... những gì bạn cần là java.nio ... theo tên là NON-BLOCKING-IO 'String host = ...; InetSocketAddress socketAddress = InetSocketAddress mới (máy chủ, 80); channel = SocketChannel.open(); channel.configureBlocking (sai); channel.connect (socketAddress); ' – Ali

+0

Tác vụ này, nhưng chỉ khi máy chủ KHÔNG phải là địa chỉ IP. Bất kỳ cách nào để làm cho nó hoạt động với IP cũng? – BenCole

0

Bạn hãy thử bằng cách phát hành một Giải quyết DNS?

Bạn có thể thử với:

public static InetAddress[] getAllByName(String host) 

nhưng tôi không chắc chắn nếu điều này sẽ đòi hỏi thời gian chờ quá ..

+0

Điều này hoạt động bằng cách ném UnknownHostException, nhưng chỉ khi máy chủ KHÔNG phải là địa chỉ IP. – BenCole

+0

Không đọc bạn đã có yêu cầu đó, xin lỗi – Jack

2

Bạn cần tạo một interface gọi NetworkListener, ví dụ

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

Tiếp theo, tạo một lớp và gọi nó là NetworkStatusThread, ví dụ

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(); 
     } 
    } 

} 

Sau đó, trong lớp học của bạn mà instantiates Thread , hãy thực hiện việc này:

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

Ngoài ra, trong lớp học đó, bạn cần phải implement số NetworkListener, để nhận cuộc gọi lại.

Trong run() phương pháp của bạn ở trên, bạn có thể thực hiện mã bằng cách @Ali, nhưng vượt qua tình trạng của tôi:

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"); 
    } 
+0

Cảm ơn! Trước đây tôi đã sử dụng Timer và một lớp con ẩn danh của TimerTask, nhưng tôi sẽ cung cấp cho nó một shot. – BenCole

+0

Chỉ hoạt động với các kết nối được kết nối internet. Câu hỏi cho là một sự thay đổi trong kết nối mạng, không kết nối với google – spy

3

chương trình của tôi yêu cầu thông báo ngay lập tức nếu một kết nối mạng là mất.

May mắn. Bạn không thể nhận được thông báo ngay lập tức với TCP/IP. Nó đầy đệm và thử lại và hết thời gian chờ, vì vậy nó không làm bất cứ điều gì và TCP theo thiết kế không có bất kỳ thứ gì tương ứng với 'âm quay số' hoặc bất kỳ API nào. Cách duy nhất để phát hiện một kết nối bị mất là cố gắng làm I/O trên nó.

Tôi đang sử dụng Java 5, vì vậy tôi không thể sử dụng các tính năng rất tiện dụng của NetworkInterface.

Chúng cũng sẽ không giúp bạn. Tất cả những gì họ có thể nói với bạn là liệu một NIC có lên hay xuống, không có gì về trạng thái kết nối của bạn với thế giới rộng lớn hơn.

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; 

Điều đó sẽ hết thời gian với lỗi DNS nếu bạn ngoại tuyến.

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

Ditto. Tuy nhiên, ngay cả khi nó không, socket.isConnected() sẽ luôn luôn trả về true. Các API như isConnected(), isBound(), isClosed(), chỉ cho bạn biết những gì bạn đã thực hiện với ổ cắm . Họ không cho bạn biết bất kỳ điều gì về trạng thái của kết nối . Họ không thể, vì lý do tôi đưa ra ở trên.

Và bạn quên đóng ổ cắm trong trường hợp ngoại lệ, vì vậy bạn bị rò rỉ tài nguyên.

Tôi cần phương thức sẽ trả lại ngay lập tức.

Không thể vì lý do được đưa ra. Bạn cần phải thiết kế lại xung quanh việc nhận ra rằng chức năng này không tồn tại.

+0

Thực ra, tôi đã có thể hình dung điều này bằng cách sử dụng chức năng của NetworkInterface (tôi nghĩ). Kiểm tra chỉnh sửa thứ 2 ở trên. Ngoài ra, tôi không biết nếu bạn nhìn thấy, nhưng tôi gọi 'socket.close()' ngay sau khi gọi 'isConnected()' .... – BenCole

+0

Bạn quên đóng socket trong trường hợp ngoại lệ. – EJP

Các vấn đề liên quan