Checking Host Reachability/Availability in Android

前端 未结 4 613
再見小時候
再見小時候 2020-12-07 20:53

Ive been trying to do what i thought would be a simple reachability of host test at the beginning of my apps internet ventures, but documentation isnt helping and neither ar

相关标签:
4条回答
  • 2020-12-07 21:40

    Try this one:

    boolean reachable = false;
    
    try {
        reachable = InetAddress.getByName("www.example.com").isReachable(2000);
    } catch (IOException e) {
        e.printStackTrace();
        reachable = false;
    }
    
    if (reachable) { 
        // do your work here 
    } 
    

    But this could fail even if the web server is up and running perfectly because of the way how isReachable(int timeout) is implemented:

    Test whether that address is reachable. Best effort is made by the implementation to try to reach the host, but firewalls and server configuration may block requests resulting in a unreachable status while some specific ports may be accessible. A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

    0 讨论(0)
  • 2020-12-07 21:42

    It's not pretty but this is how I did it:

    boolean exists = false;
    
    try {
        SocketAddress sockaddr = new InetSocketAddress(ip, port);
        // Create an unbound socket
        Socket sock = new Socket();
    
        // This method will block no more than timeoutMs.
        // If the timeout occurs, SocketTimeoutException is thrown.
        int timeoutMs = 2000;   // 2 seconds
        sock.connect(sockaddr, timeoutMs);
        exists = true;
    } catch(IOException e) {
        // Handle exception
    }
    
    0 讨论(0)
  • 2020-12-07 21:54

    To check connectivity you could use:

    public boolean isOnline(Context context) { 
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);    
        NetworkInfo netInfo = cm.getActiveNetworkInfo();    
        return netInfo != null && netInfo.isConnectedOrConnecting();
    }
    

    If it reports a connection, you could also then check via trying to do a http get to an address and then checking the status code that is returned. if no status code is returned it's pretty certain the host is unreachable.

    0 讨论(0)
  • 2020-12-07 21:54

    A Faster Solution

    Instead of opening a complete socket connection you could use inetAddress.isReachable(int timeout). That would make the check faster but also more imprecise because this method just builds upon an echo request:

    A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

    For my use case I had to establish a connection to a web server. Therefore it was necessary to me that the service on the server was up and running. So a socket connection was my preferred choice over a simple echo request.


    Standard Solution

    Java 7 and above

    That's the code that I'm using for any Java 7 and above project:

    /**
     * Check if host is reachable.
     * @param host The host to check for availability. Can either be a machine name, such as "google.com",
     *             or a textual representation of its IP address, such as "8.8.8.8".
     * @param port The port number.
     * @param timeout The timeout in milliseconds.
     * @return True if the host is reachable. False otherwise.
     */
    public static boolean isHostAvailable(final String host, final int port, final int timeout) {
        try (final Socket socket = new Socket()) {
            final InetAddress inetAddress = InetAddress.getByName(host);
            final InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, port);
    
            socket.connect(inetSocketAddress, timeout);
            return true;
        } catch (java.io.IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    

    Below Java 7

    The try-catch-resource block from the code above works only with Java 7 and a newer version. Prior to version 7 a finally-block is needed to ensure the resource is closed correctly:

    public static boolean isHostAvailable(final String host, final int port, final int timeout) {
        final Socket socket = new Socket();
        try {
            ... // same as above
        } catch (java.io.IOException e) {
            ... // same as above
        } finally {
            if (socket != null) {
                socket.close(); // this will throw another exception... just let the function throw it
            }
        }
    }
    

    Usage

    host can either be a machine name, such as "google.com", or an IP address, such as "8.8.8.8".

    if (isHostAvailable("google.com", 80, 1000)) {
        // do you work here
    }
    

    Further reading

    Android Docs:

    • Socket
    • InetSocketAddress
    • InetAddress.getByName()
    • InetAddress.isReachable()

    Stackoverflow:

    • Preferred Java way to ping an HTTP URL for availability
    0 讨论(0)
提交回复
热议问题