1

Я использую следующий код для пост проситHttpsURLConnection EOFException

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

Но это не работает для меня.

ответ

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.

0

Это исключение EOFException говорит о том, что ответ не соответствует требованиям - возможно, не хватает пустой строки после заголовков. В этом случае некоторый код HTTP-клиента более прощающий, для меня iOS отлично справляется с ответами на сервер, но я получаю EOFException на Android с помощью HttpURLConnection.

Мой сервер использует питон SimpleHTTPServer, и я был ошибочно предполагая, все, что мне нужно сделать, чтобы указать успех был следующий:

self.send_response(200) 

Это посылает начальную строку заголовка ответа, сервер и заголовок даты, но оставляет поток в состоянии, в котором вы также можете отправлять дополнительные заголовки. HTTP требует дополнительной новой строки после заголовков, чтобы указать, что они завершены. Если эта новая строка отсутствует, когда вы пытаетесь получить тело ввода InputStream или код ответа и т. Д. С HttpURLConnection, тогда он выдает исключение EOFException (что на самом деле разумно, думая об этом). Некоторые HTTP-клиенты действительно принимали короткий ответ и сообщали код результата успеха, который привел ко мне, возможно, несправедливо указывая пальцем на HttpURLConnection.

Я изменил мой сервер, чтобы сделать это вместо того, чтобы:

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

Нет больше EOFException с этим кодом. Возможно, решения «Соединение: закрыть» вызывают некоторое поведение на некоторых серверах, которые могут работать вокруг этого (например, чтобы гарантировать, что ответ действителен до закрытия), но это было не так с python SimpleHTTPServer, и основная причина оказалась моя вина.

NB: Есть некоторые ошибки на Android pre-Froyo (2.2), относящиеся к связям с живым подключением - см. Запись в блоге здесь: http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html. Мне еще предстоит увидеть убедительные доказательства ошибок с новыми версиями Android.