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(); } }
额外注意事项
- 客户端保持复用同一个Socket和流对象即可,当前客户端代码这部分逻辑正确。
- 需处理连接断开的异常场景,避免线程阻塞或崩溃。
- 若多个客户端线程访问共享资源(如Model中的数据),需添加同步控制保证线程安全。
内容的提问来源于stack exchange,提问作者Dabchinsky
相关产品推荐
相关产品推荐

