Java Socket编程服务端报错及重复接收输入问题咨询
嘿,这个问题我之前做Socket通信时也踩过坑!咱们先拆解下你遇到的两个核心问题:服务端收到四次输入副本、以及报错,然后一步步解决。
问题根源分析
1. 服务端收到四次输入副本的常见原因
- 客户端数据发送逻辑重复:比如你可能多次调用了写数据的方法,或者没正确处理输出缓冲区,导致同一份数据被重复发送;也可能是没使用合适的分隔符(比如换行),服务端读取时把一段数据拆成了多次读取。
- 服务端读取逻辑漏洞:如果服务端的读取循环没设置终止条件,或者错误地重复读取了缓冲区里的残留数据,就会出现“收到副本”的情况。
2. 服务端报错的核心原因
最可能的情况是:客户端发送exit后直接关闭了连接,但服务端还在尝试从输入流读取数据,这时候会触发EOFException或者ConnectionResetException——因为连接已经被客户端主动切断了,服务端没及时处理这个断开信号。
修正后的代码示例
我给你整理了能正常运行的客户端和服务端代码,解决上述问题:
客户端代码(修正版)
import java.io.*; import java.net.Socket; public class StringClient { public static void main(String[] args) { // 用try-with-resources自动关闭资源,避免泄漏 try (Socket socket = new Socket("localhost", 8888); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 第二个参数设为true,自动flush输出缓冲区,避免数据滞留/重复发送 PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { // 发送两个字符串,用换行符作为分隔符 out.println("Hello"); out.println("StackOverflow"); // 接收服务端返回的拼接结果 String response = in.readLine(); System.out.println("服务端返回:" + response); // 发送exit信号关闭连接 out.println("exit"); } catch (IOException e) { e.printStackTrace(); } } }
服务端代码(修正版)
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class StringServer { public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(8888)) { System.out.println("服务端启动,等待客户端连接..."); while (true) { // 每个客户端连接单独处理,用try-with-resources自动关闭Socket try (Socket clientSocket = serverSocket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) { String inputLine; StringBuilder sb = new StringBuilder(); int inputCount = 0; // 读取客户端数据,直到收到exit或者读满两个字符串 while ((inputLine = in.readLine()) != null) { if ("exit".equals(inputLine)) { break; } if (inputCount < 2) { sb.append(inputLine); inputCount++; } } // 只有收到两个有效字符串时才返回结果 if (inputCount == 2) { String combined = sb.toString(); out.println("拼接结果:" + combined + ",长度:" + combined.length()); } } catch (IOException e) { // 捕获客户端断开的异常,避免服务端崩溃 System.out.println("客户端连接异常断开:" + e.getMessage()); } } } catch (IOException e) { e.printStackTrace(); } } }
关键修正点说明
- 自动flush与资源管理:客户端用
PrintWriter(out, true)自动刷新缓冲区,避免手动flush导致的重复发送;两端都用try-with-resources自动关闭Socket和流,杜绝资源泄漏。 - 明确的读取终止条件:服务端通过
readLine() != null判断客户端是否断开连接,同时识别exit信号,避免无效的读取操作。 - 输入计数逻辑:服务端只读取前两个有效字符串,避免重复读取同一数据导致的“副本”问题。
内容的提问来源于stack exchange,提问作者user3804152
相关产品推荐
相关产品推荐

