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

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();
        }
    }
}

关键修正点说明

  1. 自动flush与资源管理:客户端用PrintWriter(out, true)自动刷新缓冲区,避免手动flush导致的重复发送;两端都用try-with-resources自动关闭Socket和流,杜绝资源泄漏。
  2. 明确的读取终止条件:服务端通过readLine() != null判断客户端是否断开连接,同时识别exit信号,避免无效的读取操作。
  3. 输入计数逻辑:服务端只读取前两个有效字符串,避免重复读取同一数据导致的“副本”问题。

内容的提问来源于stack exchange,提问作者user3804152

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:21:23