web-dev-qa-db-ja.com

Android HttpsUrlConnection eofexception

入力を読み取ろうとすると、HttpsURLConnectionがEOFExceptionをスローするという問題があります。このコードは一部のネットワークコールでは機能しますが、他のネットワークコールでは失敗します。接続から何かを読み取ろうとすると、前述のエラーで失敗します。

例:

urlConnect.getResponseCode() // will throw error
urlConnect.getResponseMessage() // will throw error
BufferedInputStream in = new BufferedInputStream(urlConnect.getInputStream()); //will throw error

それぞれのスタックトレースは次のとおりです。

getResponse:

03-14 09:49:18.547: W/System.err(6270): Java.io.EOFException
03-14 09:49:18.547: W/System.err(6270):     at libcore.io.Streams.readAsciiLine(Streams.Java:203)
03-14 09:49:18.547: W/System.err(6270):     at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.Java:573)
03-14 09:49:18.547: W/System.err(6270):     at libcore.net.http.HttpEngine.readResponse(HttpEngine.Java:821)
03-14 09:49:18.547: W/System.err(6270):     at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.Java:283)
03-14 09:49:18.547: W/System.err(6270):     at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.Java:495)
03-14 09:49:18.547: W/System.err(6270):     at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.Java:134)

BufferedInputStream:

03-14 09:39:14.077: W/System.err(5935): Java.io.EOFException
03-14 09:39:14.077: W/System.err(5935):     at libcore.io.Streams.readAsciiLine(Streams.Java:203)
03-14 09:39:14.077: W/System.err(5935):     at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.Java:573)
03-14 09:39:14.077: W/System.err(5935):     at libcore.net.http.HttpEngine.readResponse(HttpEngine.Java:821)
03-14 09:39:14.077: W/System.err(5935):     at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.Java:283)
03-14 09:50:46.547: W/System.err(6476):     at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.Java:177)
03-14 09:50:46.547: W/System.err(6476):     at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.Java:271)

助けてくれてありがとう

リック

[〜#〜] edit [〜#〜]私の答えが見つかりました:

これは十分に文書化された答えではありませんでした。 Androidの新しいバージョンの一部に表示されますが、URL接続のリサイクルにバグがあります。これを修正するには(パフォーマンスの問題があるかもしれませんが)、追加する必要がありました:

if (Build.VERSION.SDK != null
&& Build.VERSION.SDK_INT > 13) {
urlConnect.setRequestProperty("Connection", "close");
}

ありがとう!

リック

40
user1883083

誰かが私が編集する代わりに自分の質問に答えることを要求しました。答えはここにあります。

これは十分に文書化された答えではありませんでした。 Androidの新しいバージョンの一部に表示されますが、URL接続のリサイクルにバグがあります。これを修正するには(パフォーマンスの問題があるかもしれませんが)、追加する必要がありました:

if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
    urlConnect.setRequestProperty("Connection", "close");
}
42
user1883083

サーバーを指定しないので、潜在的にそれは自分で実装したカスタムのものです。 HTTP仕様では、応答がまったく正しくない可能性があります。

私のサーバーはpython SimpleHTTPServerを使用していました。

self.send_response(200)

これにより、最初の応答ヘッダー行、サーバー、日付ヘッダーが送信されますが、ストリームは追加のヘッダーも送信できる状態のままになります。 HTTPでは、ヘッダーの終了を示すために、ヘッダーの後に追加の新しい行が必要です。 HttpURLConnectionを使用して結果本文InputStreamまたは応答コードなどを取得しようとしたときにこの新しい行が存在しない場合は、EOFExceptionがスローされます(実際には妥当なことです)。一部のHTTPクライアントは短い応答を受け入れ、成功結果コードを報告したため、おそらくHttpURLConnectionを不当に指しています。

代わりにこれを行うようにサーバーを変更しました(適切な測定のためにContent-Lengthを追加):

self.send_response(200)
self.send_header("Content-Length", "0")
self.end_headers()

そのコードでEOFExceptionはもうありません。 「Connection:close」ソリューションが特定のサーバー上でこれを回避する動作をトリガーする可能性があります(たとえば、閉じる前に応答が有効であることを確認する)が、python SimpleHTTPServer 、そして根本原因は私のせいであることが判明しました。

注:キープアライブ接続に関連するAndroid pre-Froyo(2.2)にはいくつかのバグがありますが、この質問にはAndroid新しいバージョンのバグ。

1
tangobravo

最初に、URLに予期しない改行( '\ n'または '\ r\n')が含まれているかどうかを確認します。含まれている場合、応答の読み取り時にEOFExceptionが発生します。改行はHTTPパッケージをトランキングし、サーバーはクライアントがより多くの送信データを持っていると判断するため、応答はありません。応答を読み取ろうとすると、すぐにEOFが返されます。

リクエストが有効であることを確認したら、他の人から提供されたソリューションを試してください。

1
alexhilton

私はgoogle-api-Java-clientからNetHttpTransportを使用しているので、RequestPropertyの設定方法が実際には明らかではなかったため、ApacheHttpTransportを使用するように切り替えましたが、問題はなくなりました。

0
Phuah Yee Keat