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
相关产品推荐
相关产品推荐

