【问题标题】:Using HttpURLConnection on Android在 Android 上使用 HttpURLConnection
【发布时间】:2010-03-05 20:32:32
【问题描述】:

我正在尝试连接在我的 android 应用程序中运行的网络服务器,但由于某种原因它失败了。

我可以正常连接到网页并使用我的手机浏览器,我也可以使用下面的代码连接到谷歌,但由于某种原因我的代码无法连接到我的网络服务器。如果我在端口 80 上托管服务器,我每次都会收到错误代码 503,如果我在 8080 上托管它(这是最好的),我会收到一个超时异常,如下所示。

03-05 20:12:22.432: WARN/System.err(29254): java.net.SocketException: The operation timed out
03-05 20:12:22.602: WARN/System.err(29254):     at org.apache.harmony.luni.platform.OSNetworkSystem.connectSocketImpl(Native Method)
03-05 20:12:22.602: WARN/System.err(29254):     at org.apache.harmony.luni.platform.OSNetworkSystem.connect(OSNetworkSystem.java:125)
03-05 20:12:22.602: WARN/System.err(29254):     at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:227)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:521)
03-05 20:12:22.612: WARN/System.err(29254):     at java.net.Socket.connect(Socket.java:1019)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:67)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionManager$ConnectionPool.getHttpConnection(HttpConnectionManager.java:151)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionManager.getConnection(HttpConnectionManager.java:73)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.getHTTPConnection(HttpURLConnection.java:826)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:812)
03-05 20:12:22.612: WARN/System.err(29254):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:1275)
03-05 20:12:22.612: WARN/System.err(29254):     at com.project.library.remailer.ServerSelect.downloadDirectory(ServerSelect.java:84)
03-05 20:12:22.622: WARN/System.err(29254):     at com.project.main.NewMessage$3$1$1.run(NewMessage.java:156)

代码是:

try {
    URL url = new URL(directoryLocation);
    HttpURLConnection httpURLConnection = (HttpURLConnection) url
            .openConnection();

    // The line below is where the exception is called
    int response = httpURLConnection.getResponseCode();                 
    if (response == HttpURLConnection.HTTP_OK) {


        // Response successful
    InputStream inputStream = httpURLConnection.getInputStream();

    // Parse it line by line
    BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(inputStream));
    String temp;
    while ((temp = bufferedReader.readLine()) != null) {
        // Parsing of data here
    }
       } else {
            Log.e("SAMES", "INCORRECT RETURN CODE: " + response);
       }
} catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

当我尝试 CommonsWare 为端口 8080 建议的链接中的代码时,我得到与以前相同的错误,即超时异常。对于端口 80,我得到以下异常,这两个错误都发生在 url.openStream() 上。

80 端口异常:

03-06 11:53:53.296: WARN/System.err(639): java.io.FileNotFoundException: http://64.197.194.165:80/path
03-06 11:53:53.376: WARN/System.err(639):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1064)
03-06 11:53:53.376: WARN/System.err(639):     at java.net.URL.openStream(URL.java:674)
03-06 11:53:53.376: WARN/System.err(639):     at com.project.library.remailer.ServerSelect.downloadDirectory(ServerSelect.java:118)
03-06 11:53:53.376: WARN/System.err(639):     at com.project.main.NewMessage$3$1$1.run(NewMessage.java:156)

我也尝试使用以下代码:

HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(directoryLocation);
        try
        {
            HttpResponse response = client.execute(request);
            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line;
            while((line = reader.readLine()) != null) {
                Log.e("SAMES", line);
        }

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

但是,这导致了端口 8080 的相同超时错误,当调用 client.execute(response) 时会发生这种情况。

对于 80 端口,我得到一个网页,它说它无法连接,其中很多 HTML 编辑,但它在页面上说的主要内容是:

03-06 13:10:23.576:错误/SAMES(1267):Web 服务器可能已关闭、太忙或遇到其他问题,无法响应请求。您不妨稍后再试。

【问题讨论】:

  • 如果需要,我也可以提供网络服务器代码。我还在清单中添加了互联网,所以这不是问题
  • 最后发生了同样的异常。尽管我发现的错误是为 HttpURLConnection 的请求标头属性设置了一个空值。也许这对某人有帮助。

标签: android webserver httpurlconnection


【解决方案1】:

各种注释:

  • 您没有指明超时发生的位置。
  • 您可以尝试this example,它使用的 URL 与您不同。
  • 您在端口 80 上的错误代码 503 应该会在您的服务器上产生一些可能有用的错误信息。
  • 您的手机和网络服务器之间是否有任何代理服务器或其他东西?
  • 您是否尝试过同时使用 WiFi 和 3G?
  • 您可以尝试切换到 HttpClient,看看是否能获得更好的结果或错误消息。

【讨论】:

  • 在上面的代码中附加了我对尝试新代码的回复。在网络服务器上,它旨在在连接通过时打印响应,但它并没有说明任何人正在连接以进行上述任何尝试。我会稍微测试一下 HttpClient 并从中得到结果。此外,我只能使用 3G 自动取款机,而且在 Wifi 上进行测试会很困难。据我所知,我的手机和网络服务器之间也没有代理服务器。
  • 您的运营商很可能在您的手机和服务器之间有代理服务器。可以想象,他们可能不支持端口 8080,尽管我觉得这有点不寻常。特别是对于您的端口 80 测试,请查看您的服务器是否真的注册了命中。 FWIW,我建议使用 HttpClient 进行文本响应的 ResponseHandler 模式。
  • 我认为没有代理,因为当我使用手机的普通浏览器时,无论端口如何,我都可以访问网页。所以我的代码一定有问题。
【解决方案2】:

您的问题太复杂(在我看来)无法完全解决,所以我想分享一下我最近遇到的一个问题的发现,这正是您在评论中描述的原因:

// The line below is where the exception is called
int response = httpURLConnection.getResponseCode();

同一段代码在我的一个课程中引起IOException - 每次,在每个有效的URL 上,所以很明显问题出在代码中 - 看起来和你的一样 - 简单,没有标题设置,上面没有类似教程的示例。然后我注意到我看到的每个示例甚至都没有调用URLConnection.connect() 方法 - 所以我想:实际连接何时发生?标准的HttpURLConnection 使用模式是什么样的?

不幸的是,关于该主题的文档很少。所以我做了一些谷歌搜索,发现了这篇博文:HttpURLConnection's Dark Secrets - by Tim Bray,这对于编写更复杂的HttpURLConnection use-ceses 非常有用。它还为我的问题提供了答案 - 让我引用相关行:

// this opens a connection, then sends GET & headers 
in = conn.getInputStream(); 

// can't get status before getInputStream.  If you try, you'll
//  get a nasty exception.
http_status = conn.getResponseCode();

// better check it first
if (http_status / 100 != 2) {
   // redirects, server errors, lions and tigers and bears! Oh my!
}

看到第一条和第二条评论了吗?好吧,当您知道实际的网络连接是由HttpURLConnection.getInputStream() 发起的(HttpURLConnection.getOutputStream() 如果您向服务器发送任何内容)时,这很有意义。调用getResponseCode() 之后 getInputStream() 解决了我的问题。

【讨论】:

    【解决方案3】:

    如果您在调用url.openConnection() 之后尝试调用httpURLConnection.connect() 会发生什么?

    【讨论】:

    • 我试过了,结果如下。当我尝试连接到服务器上的端口 80 时,我得到了 getResponse90 函数调用,然后出现 503 错误。当我尝试使用端口 8080 时,我在 connect() 函数调用中得到超时异常
    【解决方案4】:

    只有具有 root 权限的应用才能打开 1024 以下的端口 - 这就是端口 80 的问题。

    【讨论】:

    • 那是服务器。他不是在写服务器。否则这将意味着每个应用程序都具有 root 权限,当然不是这样。
    猜你喜欢
    • 2013-07-30
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    相关资源
    最近更新 更多