如何让Java服务器持续监听客户端连接而不退出

java服务器在处理完一个客户端请求后立即终止,是因为当前代码仅接受一次连接并读取数据,之后程序自然结束;要实现持续服务,需将连接处理逻辑放入无限循环中,并正确管理资源。

要让 Java 服务器长期运行、持续响应多个客户端连接(而非处理完一个就退出),关键在于:将单次连接处理逻辑置于 while (true) 循环中,并为每个新连接创建独立的处理流程。当前代码使用了 try-with-resources 语句,虽然能自动关闭资源,但也导致整个 ServerSocket 和首个 Socket 在一次会话结束后被关闭——这正是服务器“退出”的根本原因。

✅ 正确做法是:

  • 外层保持 ServerSocket 长期存活,持续调用 accept() 等待新连接;
  • 每次 accept() 返回一个新 Socket 后,在独立作用域或新线程中处理该连接;
  • 避免将 ServerSocket 写入 try-with-resources,否则它会在首次循环结束时被关闭。

以下是改进后的完整 Java 服务器示例(单线程轮询版,适合学习理解):

import java.io.*;
import java.net.*;

public class EchoServer {
    public static void main(String[] args) {
        int port = 4444;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Echo server started on port " + port);

            while (true) { // ? 核心:永不停止监听
                Socket clientSocket = serverSocket.accept(); // 阻塞等待新连接
                System.out.println("New connection from: " + clientSocket.getRemoteSocketAddress());

                // 为每个连接单独处理(此处为简化,未开线程;生产环境建议用线程池)
                try (
                    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                    BufferedReader in = new BufferedReader(
                        new InputStreamReader(clientSocket.getInputStream())
                    )
                ) {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        System.out.println("Received: " + inputLine);
                        out.println(inputLine); // 回显
                    }
                    // 客户端断开时 readLine() 返回 null,退出内层循环
                    System.out.println("Client disconnected.");
                } catch (IOException e) {
                    System.err.println("Error handling client: " + e.getMessage());
                } finally {
                    clientSocket.close(); // 显式关闭当前连接,不影响 serverSocket
                }
            }
        } catch (IOException e) {
            System.err.println("Server startup failed: " + e.getMessage());
        }
    }
}

⚠️ 注意事项:

  • 不要把 serverSocket.accept() 放进 try-with-resources:否则循环第一次结束后 serve

    rSocket 被关闭,后续 accept() 将抛出 SocketException。
  • readLine() 返回 null 表示客户端已关闭输出流(如调用 conn.Close()),这是正常终止信号,不是错误,无需打印异常。
  • 若需并发处理多个客户端(例如同时响应 10 个请求),应在 accept() 后立即启动新线程或提交至 ExecutorService,避免阻塞后续连接。
  • Go 客户端发送后立即关闭连接是标准行为,Java 服务端应优雅处理这种“短连接”,无需修改客户端。

? 总结:服务器持续运行的本质,是分离“监听”与“服务”生命周期——ServerSocket 负责永远等待,每个 Socket 负责单次会话。掌握这一模式,是构建健壮网络服务的第一步。