HttpUrlConnection.openConnection не работает второй раз

Я знаю, что эта проблема должна быть исправлена ​​с помощью 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)

Есть ли у кого-то представление о том, что здесь не так? Спасибо!

Ответ 1

Я решил проблему. Здесь я оставляю вам код, если это может быть полезно для кого-то. В основном я вижу тенденцию к 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());

Ответ 2

Пул соединений, используемый 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());

Ответ 3

Вам не нужен System.setProperty("http.keepAlive", "false");

Все, что вам нужно, это conn.setRequestProperty("connection", "close");

это устраняет проблему, но эффективно убивает, сохраняя права и, следовательно, потенциально делает несколько подключений медленнее (что является позором). Я просматривал трекер трекинга, но ничего не мог найти.

@fonetik, знаете ли вы, что это уже достигнуто с гармонией? Я имею в виду не то, что это помогает, так как еще один связанный с http дефект luni по-прежнему не назначен после более чем месяца.

Ответ 4

эта ошибка была исправлена ​​в версии Android2.3, поскольку мы знаем, что System.setProperty("http.keepAlive", "false"); не очень хорошее решение, потому что на мобильном устройстве каждое соединение каждый раз связано с высокой стоимостью.

Ответ 5

Я считаю, что ваша проблема заключается в порядке вашего кода. Проверьте эти методы в JavaDocs URLConnection - setRequestProperty не следует вызывать после того, как соединение выполнено на mUrl.openConnection(). Он может работать в первый раз, потому что соединение выполнено, а затем вы меняете настройки, которые не влияют ни на что, до следующего попытки соединения. Попробуйте вместо этого использовать конструктор HttpURLConnection, чтобы вы могли вызвать connect() после того, как вы установили свойства.

Ответ 6

Когда я пытаюсь открыть https-соединение, он работает нормально, но второй раз он терпит неудачу, потому что я установил значение системного свойства вместо соединения HttpsURLConnection. У меня есть ошибка java.io.IOException: Write: проблема ввода-вывода при открытии соединения https второй раз. Я использовал следующий код в своем приложении.

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

Если вы установите системное свойство, оно применимо для всего приложения. Если вы хотите, чтобы reset совпал, вы можете следовать двум путям. Во-первых, вам нужно обновить сервер, а во-вторых, вам нужно изменить HttpsURLConnection.setRequestProperty, который указан выше, где это необходимо.