これが最も簡単な方法での質問です。
HttpUrlConnection オブジェクトを使用して、プロキシ経由でサーバーへの HTTPS 接続を作成します。
プロキシは接続を閉じますが、コードは同じ接続を再利用しようとします。そして、EOFExceptionが発生します。
このような場合はどのように処理すればよいですか?
これが最も簡単な方法での質問です。
HttpUrlConnection オブジェクトを使用して、プロキシ経由でサーバーへの HTTPS 接続を作成します。
プロキシは接続を閉じますが、コードは同じ接続を再利用しようとします。そして、EOFExceptionが発生します。
このような場合はどのように処理すればよいですか?
1月8日にAndroidでこの問題が修正されたことが判明しました[1]。この修正により、基本的に古い接続がリサイクルされたものとしてマークされ、内部でリクエストが再試行されます。
今のところこれを修正するには、スタックオーバーローを防ぐために再試行制限でEOFExceptionが発生した場合に、要求を再試行することをお勧めします。
通常の HTTP 接続でもこの問題が発生しました。最初のリクエストは成功しましたが、2 番目のリクエストは EOFException で失敗しました。
結局、削除して修正しました...
urlConnection.setChunkedStreamingMode(0);
...HttpUrlConnection から。
私が呼び出している Web サーバーは、チャンクされたデータをうまく処理できない可能性があります。わからない。
接続を再利用したくない場合は、解放してください。
finally {
urlConnection.disconnect();
}
同じ HttpURLConnection インスタンスを再利用しようとするべきではありません。「クラスの概要」の一番下の行にあるドキュメントは言う
HttpURLConnection の各インスタンスは、1 つの要求/応答ペアに使用できます。
Keep-Alive 接続は別のレベルで機能します。切断に関するドキュメントを参照してください: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()
他の Java 実装とは異なり、再利用可能なソケット接続が閉じられるとは限りません。HTTP 要求を発行する前に、http.keepAlive システム プロパティを false に設定することにより、すべての接続の再利用を無効にすることができます。
したがって、常に新しい HttpURLConnection を使用し、ソケット プール ハンドルを再利用できるようにする必要があります。サーバーによって閉じられたソケットを再利用しようとすると、問題が発生する可能性があります。これについては、この質問への回答で対処します: Android HttpUrlConnection EOFException
Froyo (2.2) より前のキープアライブ接続には明らかにバグがあったため、これらの古いデバイスではキープアライブを無効にすることをお勧めします。
私の場合、サーバーが完全な応答を送信しなかったために EOFException が発生しました。詳細については、https ://stackoverflow.com/a/27845939/2335025 を参照してください。
このメソッドを使用してサーバーからデータを取得し、入力トリムを文字列に変換してから、さらに使用するために解析できます。
public static InputStream getUrlData(final String url)
throws URISyntaxException, ClientProtocolException, IOException {
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet method = new HttpGet(new URI(url));
final HttpResponse res = client.execute(method);
return res.getEntity().getContent();
}
同じ HttpURLConnection インスタンスを再利用しようとするべきではありません。「クラスの概要」の一番下の行にあるドキュメントは言う
HttpURLConnection の各インスタンスは、1 つの要求/応答ペアに使用できます。
Keep-Alive 接続は異なるレベルで機能します。切断に関するドキュメントを参照してください: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()
他の Java 実装とは異なり、再利用可能なソケット接続が閉じられるとは限りません。HTTP 要求を発行する前に、http.keepAlive システム プロパティを false に設定することにより、すべての接続の再利用を無効にすることができます。
したがって、常に新しい HttpURLConnection を使用し、ソケット プール ハンドルを再利用できるようにする必要があります。
Froyo (2.2) より前のキープアライブ接続には明らかにバグがあったため、これらの古いデバイスではキープアライブを無効にすることをお勧めします。
私の場合、サーバーが完全な応答を送信しなかったことが EOFException の原因でした。詳細については、https ://stackoverflow.com/a/27845172/2335025 を参照してください。
おそらくhttpClient
「バグが多く」、非推奨ですが、JellyBean のこの問題は大きな問題です。私はKsoap2を使用しているので、提案されたすべての回答を試しました。
System.setProperty("http.keepAlive", "false");
httpTransportSE.getServiceConnection().setRequestProperty("Connection", "close");
httpTransportSE.getServiceConnection().disconnect();
何も機能しませんでした - 私の解決策は、使用している Ksoap2 のバージョンを 3.1.1 から 2.6.5 にロールバックすることでした。2.6.5 を使用すると、この問題は大幅に軽減されます。まだテスト中ですが、おそらく解決することさえあります。
このコードを試してください:`
Httppost メソッド:
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
HttpClient client = new DefaultHttpClient(httpParams);
HttpPost request = new HttpPost("put_url");
request.setHeader("Content-Type", "application/xml");
String file = resourceXml();
StringEntity se = null;
try {
se = new StringEntity(file);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
se.setContentEncoding("UTF-8");
se.setContentType("application/xml");
request.setEntity(se);
HttpResponse response = null;
try {
response = client.execute(request);
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
HttpEntity entity = response.getEntity();
InputStream is = null;
try {
is = entity.getContent();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String _response = convertStreamToString(is);
Log.i(TAG, "Response:" + _response);
// Check if server response is valid code
int res_code = response.getStatusLine().getStatusCode();
Log.i(TAG, "status_code" + res_code);
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
`
ストリームを文字列に変換するには:`
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is),
8192);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}`