【问题标题】:HttpsUrlConnection EOFExceptionHttpsUrlConnection EOFException
【发布时间】:2014-02-12 09:08:33
【问题描述】:

我正在使用以下代码进行发布请求

public String executeHttpPost(String uri, String data) {

    HttpURLConnection conn = null;
    URL url = null;
    String s = null;

    try {

        url = new URL(uri);

         conn = (HttpURLConnection) url.openConnection();

        if (conn instanceof HttpsURLConnection) {
            Log.d("HTTPS", "HttpsUrl");
        }

        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(data);
        wr.flush();

        DisplayResponseHeaders(conn);

        s = readStream(conn.getInputStream());
        Log.d("body", s);

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        s = null;
        e.printStackTrace();
    } finally {
        conn.disconnect();
    }
    return s;
  }

当我通过 http 使用它时,一切正常,但通过 https 我得到了

 java.io.EOFException
 at libcore.io.Streams.readAsciiLine(Streams.java:203)
 at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573)
 at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821)
 at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283)
 libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
 libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
 ru.fors.remsmed.fragment.NetHelper.executeHttpPost(NetHelper.java:234)
 ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:424)
 ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:1)
 android.os.AsyncTask$2.call(AsyncTask.java:287)
 java.util.concurrent.FutureTask.run(FutureTask.java:234)
 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
 java.lang.Thread.run(Thread.java:856)
 threadid=14: thread exiting with uncaught exception (group=0x40a71930)

我在 httpsurlconnection 中发现了关于回收连接错误的问题以及可能的解决方案:

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

但这对我不起作用。

【问题讨论】:

    标签: android httpurlconnection eofexception httpsurlconnection


    【解决方案1】:

    尝试像这样更改您的代码:

        conn.setRequestProperty("Content-Type",
                                "application/x-www-form-urlencoded; charset: UTF-8");
        byte[] output = data.getBytes("UTF-8");
        conn.setFixedLengthStreamingMode(output.length);
    
        os = conn.getOutputStream();
        os.write(output);
        os.flush();
        os.close();
    
        DisplayResponseHeaders(conn);
    
        if (conn.getResponseCode() == 200) { // or other 2xx code like 204
    
            s = readStream(conn.getInputStream());
            Log.d("body", s);
        }
        else {
    
            // handle error conditions like 404, 400, 500, ...
    
            // now it may be necessary to read the error stream
    
            InputStream errorStream = conn.getErrorStream();
    
            // ...
        }
    

    AFAIK 您应该始终关闭您打开的所有流。我不确定conn.disconnect() 是否正在为你这样做。

    如果您想更方便地对 HTTP(S) 请求进行编码,可以查看 DavidWebb,其中有一个库列表,可帮助您避免使用繁琐的 HttpURLConnection。

    【讨论】:

      【解决方案2】:

      该 EOFException 表明响应格式错误 - 可能在标头后缺少空行。在这种情况下,一些 HTTP 客户端代码更宽容,对我来说,iOS 可以很好地处理我的服务器响应,但我在 Android 上使用 HttpURLConnection 得到了 EOFException。

      我的服务器使用的是 python SimpleHTTPServer,我错误地认为我需要做的所有事情都表明成功:

      self.send_response(200)
      

      这会发送初始响应标头行、服务器和日期标头,但会使流处于您也可以发送其他标头的状态。 HTTP 需要在标头之后添加一个新行以指示它们已完成。当您尝试使用 HttpURLConnection 获取结果正文 InputStream 或响应代码等时,如果这条新行不存在,那么它会抛出 EOFException (这实际上是合理的,考虑一下)。一些 HTTP 客户端确实接受了简短的响应并报告了成功结果代码,这导致我可能不公平地指责 HttpURLConnection。

      我更改了我的服务器来执行此操作:

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

      该代码不再出现 EOFException。 “连接:关闭”解决方案可能会在某些可能解决此问题的服务器上触发某些行为(例如,确保在关闭之前响应有效)但python SimpleHTTPServer 的情况并非如此,根本原因结果是我的错。

      注意:Android pre-Froyo (2.2) 上存在一些与保持连接相关的错误 - 请参阅此处的博客文章:http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html。我还没有看到新版本 Android 存在错误的令人信服的证据。

      【讨论】:

        猜你喜欢
        • 2013-03-02
        • 2013-11-04
        • 1970-01-01
        • 2016-07-28
        • 2013-10-16
        • 1970-01-01
        • 2012-07-14
        • 2011-05-21
        • 2011-10-02
        相关资源
        最近更新 更多