Android中的IP回退

时间:2011-05-13 20:30:56

标签: java android web-services ip apache-commons

我正在访问服务器以进行Web服务调用。当我在与服务器相同的网络上进行开发时,我可以通过其内部IP地址访问Web服务,但不能访问其外部IP地址。但是,如果我不在网络上,我只能通过其外部IP地址访问它。尝试其中一个IP地址然后再回到另一个IP地址的最佳方法是什么?

以下是我只能访问其中一个代码的代码示例:

protected String retrieve() {
    Log.v(TAG, "retrieving data from url: " + getURL());

    HttpPost request = new HttpPost(getURL());
    try {
        StringEntity body = new StringEntity(getBody());
        body.setContentType(APPLICATION_XML_CONTENT_TYPE);
        request.setEntity(body);            

        HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(client.getParams(), SOCKET_TIMEOUT);

        HttpResponse response = client.execute(request);
        final int statusCode = response.getStatusLine().getStatusCode();


        if (statusCode != HttpStatus.SC_OK) {
            Log.e(TAG, "the URL " + getURL() + " returned the status code: " + statusCode + ".");
            return null;
        }

        HttpEntity getResponseEntity = response.getEntity();

        if (getResponseEntity != null) {
            return EntityUtils.toString(getResponseEntity);
        }
    } catch (IOException e) {
        Log.e(TAG, "error retrieving data.", e);
        request.abort();
    }

    return null;
}   

/*
 * @return the URL which should be called.
 */
protected String getURL() {
    return INTERNAL_SERVER_URL + WEB_APP_PATH;
}

8 个答案:

答案 0 :(得分:4)

查看自己的Android的IP地址。你可以像stated here那样得到它。

然后你可以决定:

  • 如果您在办公室的子网中(例如192.168.0.0/16) - 请使用内部地址
  • 如果您在其他子网中 - 使用外部地址

答案 1 :(得分:3)

基于harism的非常好的评论,我只需使用静态布尔值来选择IP,从而避免每次ping错误的IP:

public static final Boolean IS_DEBUG = true; // or false

// all your code here

if (DEBUG)
    ip = xxx.xxx.xxx.xxx;
else
    ip = yyy.yyy.yyy.yyy;

答案 2 :(得分:3)

这不是您可以在软件中轻松修复的内容。我认为正确的答案是修复将流量路由到内部Web服务器的过滤器/配置,或者通过正确配置DNS以根据您所在的位置(网络内部或外部)返回正确的IP。更多信息可以在这里找到:

Accessing internal network resource using external IP address

http://www.astaro.org/astaro-gateway-products/network-security-firewall-nat-qos-ips-more/6704-cant-acces-internal-webserver-via-external-ip.html

并通过谷歌搜索“外部IP在内部网络上不起作用”

答案 3 :(得分:3)

您可以将重试代码放在IOException的catch子句中

protected String retrieve(String url) {
    Log.v(TAG, "retrieving data from url: " + url);

    HttpPost request = new HttpPost(url);
    try {
        StringEntity body = new StringEntity(getBody());
        body.setContentType(APPLICATION_XML_CONTENT_TYPE);
        request.setEntity(body);            

        HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(client.getParams(), SOCKET_TIMEOUT);

        HttpResponse response = client.execute(request);
        final int statusCode = response.getStatusLine().getStatusCode();


        if (statusCode != HttpStatus.SC_OK) {
            Log.e(TAG, "the URL " + getURL() + " returned the status code: " + statusCode + ".");
            return null;
        }

        HttpEntity getResponseEntity = response.getEntity();

        if (getResponseEntity != null) {
            return EntityUtils.toString(getResponseEntity);
        }
    } catch (IOException e) {
        if(url.equals(EXTERNAL_URL){
            return retrieve(INTERNAL_URL);
        }

        Log.e(TAG, "error retrieving data.", e);
        request.abort();
    }

    return null;
}   

注意:像大多数人所说的那样,这对于生产版本来说可能不是一个很好的解决方案,但是对于测试它可能会很好。

答案 4 :(得分:1)

您可以更改retrieve()调用以将主机作为参数。在启动时,尝试ping每个可能的主机。对一些返回非常快的东西(比如可能是测试页面)进行简单的检索调用。完成您想要尝试的每个可能的主机。找到有效的一个后,保存该主机并将其用于将来的所有呼叫。

答案 5 :(得分:1)

第1,你应该能够在运行时处理这个案例。我非常强烈推荐vs不同版本。例如:尝试外部,如果内部失败。

同时有些启发式:
内部IP意味着网络是相同的。所以你可以检查它,如果它是相同的尝试内部地址1st,否则外部优先。 稍后,将本地IP地址的映射保存到成功连接的地址,然后查找以更改优先级。

分辨率本身可以通过超时请求服务器的根“/”来进行(如果您愿意,可以使用2个不同的线程同时执行任务)。

此外,如果您可以访问路由器/防火墙,则可以识别外部地址并正确处理它。因此,您最终可以使用正常工作的外部地址。

答案 6 :(得分:1)

我会将这种特定于环境的信息放在properties file(或者某种配置文件)中。您只需要一行文件(显然您可以根据需要更改IP地址):

serverUrl=192.168.1.1

Java已经具有用于读取和写入这些类型文件的内置功能(请参阅上面的链接)。您还可以在此文件中保留数据库连接信息等。任何环境特定的东西。

在您的代码中,您似乎使用常量来保存服务器URL。我不建议这样做。服务器URL更改时会发生什么?您需要修改和重新编译代码。但是,使用配置文件,不需要更改代码。

答案 7 :(得分:0)

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;

HttpClient client = new HttpClient();
HttpMethod method = new GetMethod("http://www.myinnersite.com");
int responseCode = client.executeMethod(method);
if (responseCode != 200) {
    method = new GetMethod("http://www.myoutersite.com");
}

等...