Android: 如何检查服务器是否可用?

39

我正在开发一个连接到服务器的应用程序。如果服务器可用,登录和数据传输现在都很正常。问题出现在服务器不可用的情况下。在这种情况下,该方法会发送一个登录请求并等待响应。

有人知道如何检查服务器是否可用(可见)吗?

必须实现以下简单逻辑的伪代码:

  1. String serverAddress =(从配置文件中读取值)//已完成
  2. boolean serverAvailable =(检查服务器serverAddress是否可用)//需要实现
  3. (这里是取决于serverAvailable的逻辑)

你可以查看https://dev59.com/TGMl5IYBdhLWcg3wiXd7#18845416以了解一种不错的方法来实现它(对我很有帮助 :)) - yossico
7个回答

51

他可能需要Java代码,因为他在开发Android应用。我相信以下Java代码可以在Android上运行:

InetAddress.getByName(host).isReachable(timeOut)

31
请注意,这种方法并不总是有效!根据文档中的描述:“该方法首先尝试使用ICMP(ICMP ECHO REQUEST)。当第一步失败时,将建立到远程主机端口7(Echo)上的TCP连接。”我发现许多Android设备不支持ICMP,而且许多服务器不接受通过端口7的TCP连接。因此,当服务器可达时,isReachable()会简单地超时。 - Paul Lammertsma
如果在主线程中使用,您还需要异步使用它。 - redbeam_

21

通过一个简单的类似ping的测试,我成功了:

static public boolean isURLReachable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://192.168.1.13");   // Change to "http://google.com" for www  test.
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(10 * 1000);          // 10 s.
            urlc.connect();
            if (urlc.getResponseCode() == 200) {        // 200 = "OK" code (http connection is fine).
                Log.wtf("Connection", "Success !");
                return true;
            } else {
                return false;
            }
        } catch (MalformedURLException e1) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }
    return false;
}

不要忘记在线程中运行此函数(而不是在主线程中)。


抱歉,我还在寻找解决方案。我发现在后台运行这个程序会消耗大量带宽,因为我认为它正在后台下载整个页面。所以现在正在尝试使用ping进程。 - Ayyappa
好的,我明白了,感谢您提供的详细信息。请随意编辑我的答案,或者提供您自己的答案 ;) - Gauthier Boaglio
@Gauthier Boaglio:我尝试使用ping,但返回结果为2且没有成功。我之前的评论可能会误导其他人,所以现在将其删除。感谢您的时间 :) - Ayyappa
权限在哪里?你有把它写在某个地方吗...? - gumuruh

8
您可以使用

标签。

InetAddress.getByName(host).isReachable(timeOut)

但是当主机在 tcp 7 上没有响应时,它无法正常工作。您可以通过使用此函数检查主机是否可用于该端口:

public static boolean isHostReachable(String serverAddress, int serverTCPport, int timeoutMS){
    boolean connected = false;
    Socket socket;
    try {
        socket = new Socket();
        SocketAddress socketAddress = new InetSocketAddress(serverAddress, serverTCPport);
        socket.connect(socketAddress, timeoutMS);
        if (socket.isConnected()) {
            connected = true;
            socket.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        socket = null;
    }
    return connected;
}

4
public static boolean IsReachable(Context context) {
    // First, check we have any sort of connectivity
    final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    final NetworkInfo netInfo = connMgr.getActiveNetworkInfo();
    boolean isReachable = false;

    if (netInfo != null && netInfo.isConnected()) {
        // Some sort of connection is open, check if server is reachable
        try {
            URL url = new URL("http://www.google.com");
            //URL url = new URL("http://10.0.2.2");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setRequestProperty("User-Agent", "Android Application");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(10 * 1000);
            urlc.connect();
            isReachable = (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            //Log.e(TAG, e.getMessage());
        }
    }

    return isReachable;
}

试一下,对我有用,并且不要忘记激活android.permission.ACCESS_NETWORK_STATE权限。


请检查您的连接或检查服务器连接。 - Dwi NetraliZme

3
public boolean isConnectedToServer(String url, int timeout) {
try{
    URL myUrl = new URL(url);
    URLConnection connection = myUrl.openConnection();
    connection.setConnectTimeout(timeout);
    connection.connect();
    return true;
} catch (Exception e) {
    // Handle your exceptions
    return false;
 }
}

2

您是否在使用HTTP?您可以在HTTP连接上设置超时,方法如下:

private void setupHttpClient() {
    BasicHttpParams httpParams = new BasicHttpParams();

    ConnManagerParams.setTimeout(httpParams, CONNECTION_TIMEOUT);
    //...

    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
            httpParams, schemeRegistry);
    this.httpClient = new DefaultHttpClient(cm, httpParams);
}

如果您执行一个请求,超过给定的时间后就会收到一个异常。


0

哦,不不,Java中的代码无法工作:InetAddress.getByName("fr.yahoo.com").isReachable(200),尽管在LogCat中我看到了它的IP地址(与20000毫秒的超时相同)。

似乎使用“ping”命令很方便,例如:

Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("ping fr.yahoo.com -c 1"); // 其他服务器,例如
proc.waitFor();
int exit = proc.exitValue();
if (exit == 0) { // 正常退出
    /* 获取执行ping命令的输出内容并解析它,
     * 以决定服务器是否可达
     */
} else { // 异常退出,因此决定该服务器不可达
    ...
}

12
由于这篇文章标记为 Android,我想提醒大家不要费力尝试此操作,因为在 Linux 上打开原始套接字需要 root 权限,所以在大多数非 root 设备上 无法工作。我已经发现它可以在一些 HTC 设备上工作,但其他设备会简单地返回“ping: icmp open socket: Operation not permitted”。 - Paul Lammertsma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接