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)
У кого-то есть представление о том, что здесь не так? Спасибо!
6 ответов
Я решил проблему. Здесь я оставляю вам код, на случай, если он кому-нибудь пригодится. В основном я вижу тенденцию в 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());
Пул соединений, используемый 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());
Вам не нужно System.setProperty("http.keepAlive", "false");
Все, что тебе нужно conn.setRequestProperty("connection", "close");
это решает проблему, но эффективно убивает сохранение в живых и, следовательно, потенциально делает несколько соединений медленнее (что обидно). Я просматривал трекер ошибок гармонии, но ничего не смог найти.
@fonetik, знаете ли вы, что это уже поднято с гармонией? Я имею в виду, что это не очень помогает, так как еще один лунный дефект, связанный с http, все еще не назначен спустя более месяца.
Как мы знаем, эта ошибка была исправлена в версии Android2.3 System.setProperty("http.keepAlive", "false");
Это не очень хорошее решение, потому что на мобильном устройстве создавать каждое соединение каждый раз стоит дорого.
Я считаю, что ваша проблема заключается в порядке вашего кода. Проверьте эти методы в URLConnection JavaDocs - setRequestProperty не должен вызываться после установления соединения с mUrl.openConnection(). Это может работать в первый раз, потому что соединение установлено, тогда вы изменяете настройки, которые ни на что не влияют, до следующей попытки установить соединение. Попробуйте вместо этого использовать конструктор HttpURLConnection, чтобы вы могли вызывать connect() после установки свойств.
Когда я пытаюсь открыть https-соединение, оно работает нормально, но во второй раз не получается, потому что я установил значение системного свойства вместо HttpsURLConnection
подключение. У меня есть java.io.IOException
: Ошибка записи: проблема ввода / вывода при повторном открытии соединения 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);
Если вы установите системное свойство, оно будет применимо для всего приложения. Если вы хотите сбросить то же самое, вы можете следовать двумя способами. Во-первых, вы должны обновить сервер, а во-вторых, вы должны изменить HttpsURLConnection.setRequestProperty
который упоминается выше, где требуется.