复杂项目即时通讯从android 5升级android x后遗症之解决#1044 java.net.SocketExceptionBroken pipe -优雅草卓伊凡|bigniu

异常解决#1044 java.net.SocketException

Broken pipe

com.guantaoyunxin.app.Reporter.post(SourceFile:7)

引言

之前说过我们因为升级了android x 带来了 几百个 兼容性问题,因此我们需要一步步一步步,一个个一个个解决,目前我们优雅草三股东大佬已经解决了几十个接近100个,其他的我们其他人也需要帮帮忙,目前至此至少整体没啥大问题不影响运营,就是优化了,问题很多但是都可以解决,毕竟我们还接入了bugly专业版的sdk可以跟踪异常,本项目本产品已经即将集大成者,本产品一旦完全修复完将会成为市场上非常不错的产品。

解决 SocketException: Broken pipe 错误

Broken pipe 错误发生在网络通信中,表示一个已建立的连接被意外中断。在 Reporter.post 方法中出现此错误,通常与HTTP请求或Socket连接有关。

错误原因分析

  1. 服务器端关闭连接:服务器在处理完请求前关闭了连接
  2. 客户端超时:客户端等待响应时间过长导致连接中断
  3. 网络不稳定:网络波动导致连接断开
  4. 大数据量传输:传输数据量过大,处理时间过长
  5. Keep-Alive问题:HTTP Keep-Alive配置不当

解决方案

方案1:增加重试机制

public void postWithRetry(String url, String data, int maxRetries) {
    int retryCount = 0;
    while (retryCount < maxRetries) {
        try {
            post(url, data); // 调用原始post方法
            return; // 成功则退出
        } catch (SocketException e) {
            retryCount++;
            if (retryCount >= maxRetries) {
                throw e; // 重试次数用完仍失败,抛出异常
            }
            // 等待一段时间后重试
            try {
                Thread.sleep(1000 * retryCount); // 指数退避
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Retry interrupted", ie);
            }
        }
    }
}

方案2:优化HTTP连接参数

// 使用HttpURLConnection时的优化设置
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);

// 设置合理的超时时间(单位:毫秒)
connection.setConnectTimeout(15000); // 15秒连接超时
connection.setReadTimeout(30000);    // 30秒读取超时

// 禁用Keep-Alive(根据实际情况选择)
connection.setRequestProperty("Connection", "close");

// 设置合理的缓冲区大小
connection.setChunkedStreamingMode(8192); // 8KB

方案3:检查数据大小和分片上传

如果是大数据量传输:

// 分片上传大文件
public void uploadLargeFile(String url, File file, int chunkSize) throws IOException {
    try (FileInputStream fis = new FileInputStream(file)) {
        byte[] buffer = new byte[chunkSize];
        int bytesRead;
        while ((bytesRead = fis.read(buffer)) != -1) {
            // 上传每个分片
            postChunk(url, buffer, bytesRead);
        }
    }
}

private void postChunk(String url, byte[] data, int length) {
    // 实现分片上传逻辑
}

方案4:使用更健壮的HTTP客户端

考虑使用OkHttp等更成熟的HTTP客户端库:

// 使用OkHttp示例
OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(15, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .writeTimeout(30, TimeUnit.SECONDS)
    .retryOnConnectionFailure(true) // 自动重试
    .build();

RequestBody body = RequestBody.create(data, MediaType.get("application/json"));
Request request = new Request.Builder()
    .url(url)
    .post(body)
    .build();

try (Response response = client.newCall(request).execute()) {
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    // 处理响应
}

预防措施

  1. 合理设置超时:根据网络状况设置适当的连接和读取超时
  2. 资源释放:确保正确关闭所有网络资源
  3. 心跳机制:长时间连接考虑添加心跳保持
  4. 错误监控:记录连接失败的具体原因和频率
  5. 网络状态检测:操作前检查网络可用性

针对 Reporter.post 方法的建议

  1. 检查方法中是否正确处理了连接关闭
  2. 确保输出流在写入完成后正确关闭
  3. 验证服务器端是否能及时处理请求
  4. 考虑添加连接池管理(如果是高频请求)
// 确保资源正确释放的模板
HttpURLConnection connection = null;
try {
    connection = (HttpURLConnection) new URL(url).openConnection();
    // 设置请求参数和写入数据...

    // 获取响应
    try (InputStream is = connection.getInputStream()) {
        // 处理响应...
    }
} finally {
    if (connection != null) {
        connection.disconnect();
    }
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐