当我调用REST API时,我得到EOFException
。我知道它说响应是空的。但它不应该。我在iOS应用程序中使用相同的API没有任何问题。
这是我的代码:
try {
url = new URL(baseUrl);
}
// Thrown when URL could not be parsed
catch (MalformedURLException me) {
Log.e(TAG, "URL could not be parsed. URL : " + baseUrl, me);
}
try {
// System.setProperty("http.keepAlive", "false");
// Set connection properties
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(method);
urlConnection.setConnectTimeout(TIMEOUT * 1000);
urlConnection.setChunkedStreamingMode(0);
urlConnection.setRequestProperty("Accept", "*/*");
urlConnection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
// urlConnection.setRequestProperty("Connection", "close");
if (method.equals("POST") || method.equals("PUT")) {
// Set to true when posting data
urlConnection.setDoOutput(true);
// Write data to post to connection output stream
OutputStream out = urlConnection.getOutputStream();
out.write(postParameters.getBytes("UTF-8"));
Log.d(TAG, "Data written to output stream.");
}
// urlConnection.connect();
try {
// Get response
in = new BufferedInputStream(urlConnection.getInputStream());
} catch (IOException e) {
Log.e(TAG,
"Exception in getting connection input stream. Input stream : "
+ in, e);
}
Log.d(TAG, "content length : " + urlConnection.getContentLength());
Log.d(TAG, "content type : " + urlConnection.getContentType());
// Read the input stream that has response
statusCode = urlConnection.getResponseCode();
Log.d(TAG, "Status code : " + statusCode);
if (statusCode >= 400) {
Log.e(TAG, "Error stream : " + urlConnection.getErrorStream().toString());
}
// Passing input stream to a function.
readStream(in, statusCode);
} catch (ProtocolException pe) {
Log.e(TAG,
"Make sure HTTP method is set before connecting to URL. Line : "
+ getLineNumber(), pe);
} catch (IllegalStateException ie) {
Log.e(TAG,
"Set connection properties before connecting to URL. Line : "
+ getLineNumber(), ie);
}
// Thrown when connecting to URL times out
catch (SocketTimeoutException se) {
Log.e(TAG, "Timeout before connecting to URL : " + baseUrl
+ ". Line : " + getLineNumber(), se);
} catch (IOException e) {
Log.e(TAG, "Exception while connecting to URL : " + baseUrl, e);
} finally {
urlConnection.disconnect();
}
我尝试了以下内容,但没有奏效。这些论文在代码中被注释掉了。 :
1)System.setProperty("http.keepAlive", "false");
2)urlConnection.setRequestProperty("Connection", "close");
3)urlConnection.connect();
语句Log.d(TAG, "Status code : " + statusCode);
未被记录。通常它有效。
Logcat屏幕截图:
答案 0 :(得分:1)
显然这是由于HTTPUrlConnection中的错误(请参阅this answer on StackOverflow)。我建议你实现一个重试机制。这就是我实施的例子:
/** POST an object on the server using the REST API. */
private int httpPOST(String path, JSONObject json) {
final static int MAX_RETRIES = 3;
int numTries = 0;
int responseCode = 0;
HttpsURLConnection urlConnection = null;
final long startTime = System.currentTimeMillis();
while (numTries < MAX_RETRIES) {
if (numTries != 0) {
LOGV(TAG, "Retry n°" + numTries);
}
// Create (POST) object on server
try {
byte[] bytes = json.toString().getBytes("UTF-8");
URL url = new URL(path);
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(bytes.length);
urlConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
LOGV(TAG, "HTTP POST " + url.toString());
OutputStream out = urlConnection.getOutputStream();
out.write(bytes);
out.close();
responseCode = urlConnection.getResponseCode();
LOGV(TAG, "HTTP POST response code: " + responseCode + " (" + (System.currentTimeMillis() - startTime)
+ "ms)");
return responseCode;
} catch (UnsupportedEncodingException e) {
LOGV(TAG, "Unsupported encoding exception");
} catch (MalformedURLException e) {
LOGV(TAG, "Malformed URL exception");
} catch (IOException e) {
LOGV(TAG, "IO exception: " + e.toString());
// e.printStackTrace();
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
numTries++;
}
LOGV(TAG, "Max retries reached. Giving up...");
return responseCode;
}
答案 1 :(得分:1)
以下代码可以帮助您
HttpEntity entity = response.getEntity();
// All the work is done for you here :)
String jsonContent = EntityUtils.toString(entity);
// Create a Reader from String
Reader stringReader = new StringReader(jsonContent);
// Pass the string reader to JsonReader constructor
JsonReader reader = new JsonReader(stringReader);
reader.setLenient(true);
readGson(reader);
...
// at the end of method return the JSON response
return jsonContent;
答案 2 :(得分:1)
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。
注意:Android之前的Froyo(2.2)存在一些与保持连接有关的错误 - 请参阅此处的博文:http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html。我还没有看到令人信服的证据证明Android的新版本存在漏洞,尽管很多StackOverflow的答案都提到了它(因此我在多个地方提出这个问题......)
答案 3 :(得分:0)