You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Socket通信遇SocketException:发送对象后无法接收响应求助

问题根源分析

出现Socket closed异常的核心原因是提前关闭了与Socket关联的输入/输出流:Java中关闭ObjectInputStream、ObjectOutputStream这类基于Socket的流时,会自动关闭底层的Socket连接,导致后续无法再进行读写操作。

  • 客户端错误原因:写完对象后立即调用out.close(),直接关闭了Socket,后续执行in.readUTF()时Socket已关闭。
  • 服务器错误原因:读取完对象后关闭ObjectInputStream,触发Socket关闭,后续尝试获取DataOutputStream时报错。

解决方案

1. 客户端代码修正

不要提前关闭ObjectOutputStream,应在读取完响应后统一关闭资源,推荐使用try-with-resources语法自动管理资源:

public class Client {
    public static void main(String[] args) {
        try (Socket soc = new Socket("localhost", 8080);
             ObjectOutputStream out = new ObjectOutputStream(soc.getOutputStream());
             DataInputStream in = new DataInputStream(soc.getInputStream())) {

            Planification p = new Planification(0, "Alex", "5070921647382", LocalDate.now(), 2, 1, LocalDate.of(2023, 1, 15), LocalTime.of(12, 0, 0));
            out.writeObject(p);
            out.flush();

            // 读取响应后由try-with-resources自动关闭所有资源
            System.out.println(in.readUTF());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 服务器代码修正

方案一:用try-with-resources统一管理Socket与流

修改handleRequest方法,确保所有通信完成后再关闭资源,同时移除run方法中手动关闭connection的代码:

private void run() throws IOException {
    ServerSocket socket = new ServerSocket(8080);
    System.out.println("Server started on port 8080");
    while (true) {
        final Socket connection = socket.accept();
        this.handleRequest(connection);
        // 移除手动关闭connection的代码,由try-with-resources处理
    }
}

private void handleRequest(Socket connection) throws IOException, ExecutionException, InterruptedException {
    try (ObjectInputStream objectInputStream = new ObjectInputStream(connection.getInputStream());
         DataOutputStream out = new DataOutputStream(connection.getOutputStream())) {

        Object command = objectInputStream.readObject();
        Future<String> result = executorService.submit(new ServiceCallable(command, this.locationsRepository, this.paymentsRepository, this.planificationsRepository, this.treatmentsRepository));
        String res = result.get();
        System.out.println(res);

        out.writeUTF(res);
        out.flush();
    }
}

方案二:手动管理资源的关闭顺序

若业务需分阶段处理输入输出,需在最后统一关闭所有资源,绝对不能提前关闭输入流:

private void handleRequest(Socket connection) throws IOException, ExecutionException, InterruptedException {
    ObjectInputStream objectInputStream = null;
    DataOutputStream out = null;
    try {
        objectInputStream = new ObjectInputStream(connection.getInputStream());
        Object command = objectInputStream.readObject();

        Future<String> result = executorService.submit(new ServiceCallable(command, ...));
        String res = result.get();
        System.out.println(res);

        out = new DataOutputStream(connection.getOutputStream());
        out.writeUTF(res);
        out.flush();
    } finally {
        // 按顺序关闭资源
        if (objectInputStream != null) objectInputStream.close();
        if (out != null) out.close();
        connection.close();
    }
}

3. ServiceCallable类修正

移除所有与Socket流相关的操作,仅专注于业务逻辑处理:

public synchronized String call() throws Exception {
    // 仅处理传入的command对象,执行验证逻辑并返回结果
    ...
    return "处理完成的响应内容";
}

内容的提问来源于stack exchange,提问作者Adrian Sârbu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:05:18