HttpUrlConnection.openConnection第二次失败

问题描述:

我知道这个问题应该用System.setProperty(“http.keepAlive”,“false”)修复; openConnection之前,但这并不适用于我。首先尝试这个代码的作品,第二个失败。即使我在少于5秒后尝试这个请求,它也可以工作。如果我等待不止于此,它再次HttpUrlConnection.openConnection第二次失败

失败,这是我的代码:

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) 

是否有人有什么这里是错的想法?。谢谢!

我解决了这个问题。在这里,我给你留下了代码,以防它可能对某人有所帮助。基本上我在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()); 
+10

谷歌现在推荐使用HttpURLConnection的,因为一些这些错误的(从姜饼开始)之后,这已得到修复: HTTP:// android-developers.blogspot.com/2011/09/androids-http-clients.html – 2011-11-07 23:20:39

+8

这个解决方案为什么解决这个问题? – 2012-04-11 11:38:51

+0

迟早,特别是随着Android M的不断增长,HttpClient正在变得有效的弃用。建议URLConnection适用于未来很长时间的应用程序。 – Josh 2015-12-16 12:52:26

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

+1

感谢您的回答,但我担心这种方式行不通。这就是API文档所说的:URLConnection只能在实例化之后但连接到远程资源之前设置。 在我的情况下,实际连接的情况: conn.getInputStream() 和标题设置 – ggomeze 2010-07-29 06:08:30

当它保持连接活着使用HttpURLConnection连接池被破坏,使得它试图使用已被服务器关闭连接。默认情况下,Android会在所有连接上设置KeepAlive。

System.setProperty("http.keepAlive", "false");是禁用保持活动的所有连接,那么你避免在连接池的bug解决方法。

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

谢谢@fonetik的答案和解释!我现在无法测试它,因为我转移到HttpClient,但我确信这可以帮助其他人。再次感谢! – ggomeze 2010-09-14 11:11:41

+0

@ user464773'System.setProperty(“http.keepAlive”,“false”);'在应用程序的所有连接上禁用_Keep Alive_。这是我们想要的,因为_Keep Alive_将始终导致错误。使用'conn.setRequestProperty(“connection”,“close”);''只为''conn'禁用_Keep Alive_,当我们忘记将它添加到任何一个连接时,就会打开一扇门。我不知道这个bug是否会让它回到和谐之中,但Android团队知道它:http://code.google.com/p/android/issues/detail?id=7786 – barrycburton 2010-10-25 22:13:23

+0

谢谢,这就是我正在寻找 – TacoEater 2013-02-20 01:23:01

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

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

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

@fonetik,你知不知道这是否已经与和谐长大的吗?我的意思不是说它帮助很大,因为另一个http相关的luni缺陷在超过一个月后仍然未被分配。

+0

conn.setRequestProperty(“connection”,“close”);为我工作。简单而有效。我正在为Android L和M使用URLconnection。 – Josh 2015-12-16 13:31:21

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

当我试图打开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