Android HttpUrlConnection.openConnection 第二次失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3352424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:51:11  来源:igfitidea点击:

HttpUrlConnection.openConnection fails second time

androidhttpurlconnection

提问by ggomeze

I know this issue should be fixed with System.setProperty("http.keepAlive", "false"); before openConnection, but that didn't work to me. First try on this code works, second one fails. Even if i try this request after less than 5 seconds, it also works. If i wait more than that, it fails again

我知道这个问题应该用 System.setProperty("http.keepAlive", "false"); 解决。在 openConnection 之前,但这对我不起作用。第一次尝试此代码有效,第二次失败。即使我在不​​到 5 秒后尝试此请求,它也可以工作。如果我等待的时间更长,它会再次失败

This is my code:

这是我的代码:

    System.setProperty("http.keepAlive", "false");
  HttpURLConnection conn = (HttpURLConnection) mURL.openConnection();
  conn.setUseCaches(false); 
  conn.setRequestProperty("Connection","Keep-Alive"); 
  conn.setRequestProperty("User-Agent", useragent);
  conn.setConnectTimeout (30000) ; 
  conn.setDoOutput(true); 
        conn.setDoInput(true); 

  consumer.sign(conn);
  InputSource is = new InputSource(conn.getInputStream());

I get the exception on last line:

我在最后一行得到异常:

java.io.IOException: Write error: I/O error during system call, Broken pipe
W/System.err( 2164):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativewrite(Native Method)
W/System.err( 2164):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.access0(OpenSSLSocketImpl.java:55)
W/System.err( 2164):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:583)
W/System.err( 2164):  at java.io.OutputStream.write(OutputStream.java:82)
W/System.err( 2164):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.sendRequest(HttpURLConnectionImpl.java:1332)
W/System.err( 2164):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.java:1656)
W/System.err( 2164):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.java:1649)
W/System.err( 2164):  at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1153)
W/System.err( 2164):  at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:253)

Does someone have an idea about what's wrong here?. Thanks!

有人知道这里有什么问题吗?谢谢!

采纳答案by ggomeze

I solved the problem. Here I leave you the code, in case it might be helpful for someone. Basically I see a trend on Google for using HttpClient/HttpGet instead of HttpUrlConnection. So I tried with those classes, and everything worked:

我解决了这个问题。我在这里给你留下代码,以防它对某人有帮助。基本上,我在 Google 上看到了使用 HttpClient/HttpGet 而不是 HttpUrlConnection 的趋势​​。所以我尝试了这些课程,一切正常:

final HttpClient client = new DefaultHttpClient();
final HttpGet conn = new HttpGet(mURL.toString());

OAuthConsumer consumer = mOAuthManager.getPostConsumer();
consumer.sign(conn);
HttpResponse response = client.execute(conn);
InputSource is = new InputSource(response.getEntity().getContent());

回答by barrycburton

The connection pool used by HttpURLConnectionwhen it is keeping connections alive is broken such that it tries to use connections that have been closed by the server. By default Android sets KeepAlive on all connections.

HttpURLConnection保持连接活动时使用的连接池已损坏,因此它尝试使用已被服务器关闭的连接。默认情况下,Android 在所有连接上设置 KeepAlive。

System.setProperty("http.keepAlive", "false");is a workaround that disables KeepAlive for all connections so then you avoid the bug in the connection pool.

System.setProperty("http.keepAlive", "false");是一种对所有连接禁用 KeepAlive 的解决方法,这样您就可以避免连接池中的错误。

conn.setRequestProperty("Connection","Keep-Alive");turns KeepAlive on for this particular connection, essentially reversing what System.setProperty("http.keepAlive", "false");does.

conn.setRequestProperty("Connection","Keep-Alive");为这个特定的连接开启 KeepAlive,本质上是颠倒了System.setProperty("http.keepAlive", "false");它的作用。

Also I always explicitly call connect()as it makes it clear where you are ending your connection setup. I'm not sure if calling this method is optional or not.

此外,我总是明确调用connect(),因为它清楚地表明您在哪里结束连接设置。我不确定调用这个方法是否是可选的。

System.setProperty("http.keepAlive", "false");
HttpURLConnection conn = (HttpURLConnection) mURL.openConnection();
conn.setUseCaches(false); 
conn.setRequestProperty("User-Agent", useragent);
conn.setConnectTimeout(30000);
conn.setDoOutput(true); 
conn.setDoInput(true); 
consumer.sign(conn);

conn.connect();

InputSource is = new InputSource(conn.getInputStream());

回答by RaB

You dont need the System.setProperty("http.keepAlive", "false");

你不需要 System.setProperty("http.keepAlive", "false");

All you need is conn.setRequestProperty("connection", "close");

所有你需要的是 conn.setRequestProperty("connection", "close");

this fixes the issue but effectively kills keep alives and therefore potentially makes multiple connections slower (which is a shame). I was looking through the harmony bug tracker but could not really find anything.

这解决了问题,但有效地杀死了保持活动,因此可能会使多个连接变慢(这是一种耻辱)。我正在查看和声错误跟踪器,但找不到任何东西。

@fonetik, do you know whether this is already raised with harmony? I mean not that it helps much since another http related luni defect is still unassigned after more than a month.

@fonetik,你知道这是否已经和谐提出了吗?我的意思并不是说它有多大帮助,因为另一个与 http 相关的 luni 缺陷在一个多月后仍未分配。

回答by allen

this bug had beed fixed in Android2.3 version,as we know System.setProperty("http.keepAlive", "false");is not a very good solution ,because on mobile device ,create each connection is every time is high cost.

这个bug已经在Android2.3版本中修复了,我们知道System.setProperty("http.keepAlive", "false");这不是一个很好的解决方案,因为在移动设备上,每次创建连接都是高成本的。

回答by user3411924

When i am trying to open https connection it is working fine but second time it fails because i have set the system property value instead of HttpsURLConnectionconnection. I have got the java.io.IOException: Write error: I/O issue while opening the https connection second time. I have used following code in my applicaiton.

当我尝试打开 https 连接时,它工作正常,但第二次失败,因为我设置了系统属性值而不是HttpsURLConnection连接。我收到了java.io.IOException:写入错误:第二次打开 https 连接时出现 I/O 问题。我在我的应用程序中使用了以下代码。

System.setProperty("http.proxyHost", proxy);
System.setProperty("http.proxyPort", port);

But when i changed the same to below it works fine.

但是当我将其更改为以下时,它工作正常。

javax.net.ssl.HttpsURLConnection ucon = (javax.net.ssl.HttpsURLConnection) urlWPF.openConnection(proxyserver);

ucon.setRequestProperty("http.proxyHost", proxy);
ucon.setRequestProperty("http.proxyPort", port);

If you set the system property, it will applicable for entire application. If you want reset the same, you can follow two ways. One is you have to take server refresh and second one is you have to change the HttpsURLConnection.setRequestPropertywhich is mentioned above where required.

如果您设置系统属性,它将适用于整个应用程序。如果你想重置相同,你可以按照两种方式。一是您必须刷新服务器,二是您必须HttpsURLConnection.setRequestProperty在需要时更改上面提到的内容。

回答by ZachM

I believe your problem lies in the order of your code. Check those methods in the URLConnection JavaDocs - setRequestProperty should not be called after the connection is made on mUrl.openConnection(). It may be working the first time because the connection is made, then you are changing settings that are not affecting anything until the next time you try to make a connection. Try using the HttpURLConnection constructor instead so you can call connect() after you have set the properties.

我相信您的问题在于您的代码顺序。检查 URLConnection JavaDocs 中的这些方法 - 在 mUrl.openConnection() 上建立连接后不应调用 setRequestProperty。它可能是第一次工作,因为已建立连接,然后您正在更改不会影响任何内容的设置,直到您下次尝试建立连接。尝试改用 HttpURLConnection 构造函数,以便在设置属性后调用 connect()。