32

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

这是我的代码:

    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());

我在最后一行得到异常:

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.access$600(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)

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

4

6 回答 6

29

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

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

conn.setRequestProperty("Connection","Keep-Alive");为这个特定的连接打开 KeepAlive,本质上是相反的System.setProperty("http.keepAlive", "false");

此外,我总是明确地打电话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());
于 2010-09-13T20:19:14.593 回答
24

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

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

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

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

于 2010-10-15T15:45:27.343 回答
3

我解决了这个问题。在这里,我将代码留给您,以防它对某人有所帮助。基本上,我在 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());
于 2010-07-29T06:43:30.037 回答
1

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

于 2011-05-28T15:56:55.330 回答
0

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

于 2010-07-29T05:40:34.323 回答
0

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

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

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

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

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

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

于 2014-03-12T17:38:28.403 回答