OkHttp请求ESP8266服务器时响应体Not Available致App崩溃求助
问题排查与解决方案
核心问题分析
ESP8266的轻量HTTP服务器与Node/Express的HTTP实现存在差异,主要体现在连接保持(Keep-Alive)处理和响应体传输完整性上,导致OkHttp在无日志拦截器时无法正确读取响应体,触发崩溃。
解决方案
1. 强制OkHttp使用Connection: close
ESP8266对HTTP长连接的支持不完善,而OkHttp默认启用Keep-Alive,导致响应体读取时出现流异常。可以通过两种方式强制关闭连接:
方式一:单个请求添加请求头
Request request = new Request.Builder() .url(BASE_URL) .header("Connection", "close") // 强制关闭连接 .build();
方式二:全局配置OkHttpClient禁用长连接
OkHttpClient client = new OkHttpClient.Builder() .connectionPool(new ConnectionPool(0, 1, TimeUnit.NANOSECONDS)) // 禁用连接池 .build();
2. 修复响应体读取与异常处理逻辑
原代码存在两个隐患:
assert语句在发布版会被忽略,无法真正避免空指针- 在UI线程读取响应体,且未妥善处理JSON解析异常,直接抛出RuntimeException导致崩溃
修改后的代码:
@Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { // 先在子线程读取响应体(string()只能调用一次) final String rawData; if (response.isSuccessful() && response.body() != null) { rawData = response.body().string(); } else { rawData = ""; } runOnUiThread(new Runnable() { @Override public void run() { if (rawData.isEmpty()) { textView.setText("请求失败"); return; } try { JSONObject rsp = new JSONObject(rawData); JSONObject dataObj = rsp.getJSONObject("data"); lightState = dataObj.getString("status"); textView.setText(lightState); } catch (JSONException e) { e.printStackTrace(); textView.setText("数据解析失败"); } } }); }
3. 修复ESP8266服务器的响应头
在ESP8266的服务器代码中,强制返回Connection: close响应头,确保所有客户端都使用短连接:
// 示例:ESP8266 WebServer响应时添加头 server.send(200, "application/json", responseJson); server.sendHeader("Connection", "close"); // 强制关闭连接
同时确保响应头包含正确的Content-Length,让OkHttp可以准确判断响应体结束位置:
server.sendHeader("Content-Length", String(responseJson.length()));
内容的提问来源于stack exchange,提问作者622
相关产品推荐
相关产品推荐

