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

Java Socket服务端仅处理一次请求后停止接收数据的问题

Java Swing客户端-服务端通信二次请求失败问题

我正在开发基于Java Swing的客户端-服务端应用,通过ObjectOutputStream发送请求。首次从LoginFrame发起登录校验请求时,服务端能接收数据、处理并返回结果,但发起第二次获取国家列表请求时,服务端不再接收数据,仿佛停止监听。

目前checkUser方法正常,调用getCountries时客户端卡在String[] check = (String[]) client1.ois.readObject();,服务端处理完首次请求后不再监听。我尝试过更换流对象、发送后flush、使用后关闭流,但均无效。


服务端代码

public void runServer() throws IOException, ClassNotFoundException {

        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("Server started and listening " + port);
        Model.getCountriesAndCities();
        System.out.println(Model.getCountries()[0]);
        System.out.println(Model.getCountriesMap());

        for (int i = 0; i < 50; i++) {
            Socket clientSocket = serverSocket.accept();
            System.out.println("serversocket accepted");
            System.out.println("before oos");
            ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
            System.out.println("before ois");
            ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
            System.out.println("server is listening");

            Map<String, Object> methodData = (Map<String, Object>) ois.readObject();
            System.out.println("Server: data received");

            String methodName = (String) methodData.get("method");
            Object arguments = methodData.get("arguments");

            Object result = invokeMethod(methodName, arguments);

            oos.writeObject(result);
            System.out.println("Server: data sent");
            oos.flush();
        }
    }

客户端代码

checkUser方法

public static int checkUser(String login, String password, Client client) {
        String query = "SELECT EXISTS(SELECT * FROM users WHERE login = '" + login + "' and password = '" + password + "') as isExist";
        String methodName = "CRUDUtils.checkUser";
        try {
            Map<String, Object> methodData = new HashMap<>();
            methodData.put("method", methodName);
            methodData.put("arguments", query);

            client1.oos.writeObject(methodData);
            System.out.println("Client: query sent");
            client1.oos.flush();

            int check = (Integer) client1.ois.readObject();
            System.out.println("chekUser: answer received");
            return check;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

getCountries方法

public static String[] getCountries(Client client) {
        String query = " ";
        String methodName = "Model.getCountries";
        ObjectOutputStream oos;
        ObjectInputStream ois;
        try {
            Map<String, Object> methodData = new HashMap<>();
            methodData.put("method", methodName);
            methodData.put("arguments", query);

            client1.oos.writeObject(methodData);
            System.out.println("Client: query sent");
            client1.oos.flush();

            System.out.println("before ois");
            String[] check = (String[]) client1.ois.readObject();
            System.out.println("getCountries: answer received");
            return check;
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

客户端启动类

public static void main(String[] args) {
        Client klientura = new Client();
        try {
            klientura.socket = new Socket("localhost", 4444);
            klientura.oos = new ObjectOutputStream(klientura.socket.getOutputStream());
            klientura.ois = new ObjectInputStream(klientura.socket.getInputStream());
            System.out.println("client connected");
            Control.client1 = klientura;
            LoginFrame loginFrame = new LoginFrame(klientura);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

问题原因分析

服务端核心逻辑错误:

  • 当前服务端for循环中,每次serverSocket.accept()都会等待新的客户端连接,处理完一次请求后不会持续监听该连接的后续请求,而是回到循环等待新连接。
  • 客户端复用同一个Socket连接发送第二次请求,但服务端已经不再关注这个连接的输入流,导致请求无法被接收。

修复方案

服务端需要为每个客户端连接单独启动线程,持续处理该连接的所有请求:

public void runServer() throws IOException {
    ServerSocket serverSocket = new ServerSocket(port);
    System.out.println("Server started and listening " + port);
    Model.getCountriesAndCities();
    System.out.println(Model.getCountries()[0]);
    System.out.println(Model.getCountriesMap());

    while (true) {
        Socket clientSocket = serverSocket.accept();
        System.out.println("New client connected");
        // 为每个客户端连接启动独立线程处理请求
        new Thread(() -> {
            try (ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
                 ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream())) {
                System.out.println("Ready to handle requests from client");
                while (!clientSocket.isClosed()) {
                    Map<String, Object> methodData = (Map<String, Object>) ois.readObject();
                    System.out.println("Server: data received");

                    String methodName = (String) methodData.get("method");
                    Object arguments = methodData.get("arguments");

                    Object result = invokeMethod(methodName, arguments);

                    oos.writeObject(result);
                    System.out.println("Server: data sent");
                    oos.flush();
                }
            } catch (IOException | ClassNotFoundException e) {
                System.out.println("Client connection closed or error occurred: " + e.getMessage());
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

额外注意事项

  1. 客户端保持复用同一个Socket和流对象即可,当前客户端代码这部分逻辑正确。
  2. 需处理连接断开的异常场景,避免线程阻塞或崩溃。
  3. 若多个客户端线程访问共享资源(如Model中的数据),需添加同步控制保证线程安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:05:04