HttpUrlConnection.openConnection第二次失败

时间:2010-07-28 11:38:18

标签: android httpurlconnection

我知道这个问题应该用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)

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

6 个答案:

答案 0 :(得分: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());

答案 1 :(得分:24)

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

您需要的只是conn.setRequestProperty("connection", "close");

这解决了问题,但有效地杀死了alives,因此可能使多个连接变得更慢(这是一种耻辱)。我正在通过和谐bug跟踪器,但无法找到任何东西。

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

答案 2 :(得分:3)

我解决了这个问题。在这里,我给你留下代码,以防它对某人有帮助。基本上我看到谷歌使用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());

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

答案 5 :(得分: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