diff --git a/src/main/java/com/example/echo/EchoServer.java b/src/main/java/com/example/echo/EchoServer.java index f55f684ccb91a654ac3993a691cb9ef5f97c0396..10dc361452b6a98e603b63d8cd2ef52f0779d26c 100644 --- a/src/main/java/com/example/echo/EchoServer.java +++ b/src/main/java/com/example/echo/EchoServer.java @@ -1,70 +1,96 @@ package com.example.echo; -import java.io.*; -import java.net.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** - * 单客户端Echo服务器 - * 这个服务器一次只处理一个客户端连接 + * 支持多客户端的Echo服务器 + * 修复语法错误 + 实现多客户端 + 连接日志 + TIME命令 + 验证clientSocket.close()问题 */ public class EchoServer { private static final int PORT = 8888; private ServerSocket serverSocket; private boolean running = false; + // 替换单线程池为固定线程池,支持多客户端 private ExecutorService executor; public EchoServer() { - executor = Executors.newSingleThreadExecutor(); + // 核心修改:固定线程池(支持多客户端,替代单线程) + executor = Executors.newFixedThreadPool(10); } /** - * 启动服务器 + * 启动服务器(修改为循环接受多客户端连接) */ public void start() throws IOException { serverSocket = new ServerSocket(PORT); running = true; System.out.println("Echo Server已启动,监听端口: " + PORT); - // 等待客户端连接 - System.out.println("等待客户端连接..."); - Socket clientSocket = serverSocket.accept(); - System.out.println("客户端已连接: " + clientSocket.getRemoteSocketAddress()); + // 核心修改:循环接受客户端连接(支持多客户端) + while (running) { + System.out.println("等待客户端连接..."); + Socket clientSocket = serverSocket.accept(); + String clientInfo = clientSocket.getRemoteSocketAddress().toString(); + // 打印连接日志 + System.out.println(getCurrentTime() + " 客户端已连接: " + clientInfo); - handleClient(clientSocket); + // 交给线程池处理(每个客户端一个任务,非单线程阻塞) + executor.submit(() -> handleClient(clientSocket, clientInfo)); + } } /** - * 处理客户端连接 + * 处理客户端连接(新增clientInfo参数用于日志) */ - private void handleClient(Socket clientSocket) { + private void handleClient(Socket clientSocket, String clientInfo) { try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) { String inputLine; - System.out.println("开始与客户端通信..."); + System.out.println(getCurrentTime() + " 开始与客户端通信: " + clientInfo); while ((inputLine = in.readLine()) != null) { + // 1. 识别TIME命令,返回系统时间 + if ("TIME".equalsIgnoreCase(inputLine.trim())) { + String currentTime = getCurrentTime(); + out.println("Server: " + currentTime); + System.out.println(getCurrentTime() + " 响应TIME命令给客户端: " + clientInfo); + continue; + } + + // 2. 处理断开连接命令 if ("bye".equalsIgnoreCase(inputLine.trim())) { - System.out.println("客户端请求断开连接"); + System.out.println(getCurrentTime() + " 客户端请求断开连接: " + clientInfo); + out.println("Server: 连接即将断开"); break; } - System.out.println("收到消息: " + inputLine); - // 将收到的消息回显给客户端 + // 3. 原Echo逻辑 + System.out.println(getCurrentTime() + " 收到[" + clientInfo + "]消息: " + inputLine); out.println("Echo: " + inputLine); } } catch (IOException e) { - System.err.println("处理客户端连接时发生错误: " + e.getMessage()); + System.err.println(getCurrentTime() + " 处理客户端[" + clientInfo + "]连接时发生错误: " + e.getMessage()); } finally { try { - clientSocket.close(); - System.out.println("客户端连接已关闭"); + // ********************* 验证clientSocket.close()的核心代码 ********************* + // 测试1:注释下面这行,会导致CLOSE_WAIT连接泄漏;取消注释则正常释放资源 + clientSocket.close(); + // 打印断开日志 + System.out.println(getCurrentTime() + " 客户端已断开: " + clientInfo); } catch (IOException e) { - System.err.println("关闭客户端连接时发生错误: " + e.getMessage()); + System.err.println(getCurrentTime() + " 关闭客户端连接时出错: " + e.getMessage()); } } } @@ -85,7 +111,15 @@ public class EchoServer { } catch (InterruptedException e) { executor.shutdownNow(); } - System.out.println("服务器已停止"); + System.out.println(getCurrentTime() + " 服务器已停止"); + } + + /** + * 工具方法:获取格式化的系统时间 + */ + private String getCurrentTime() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return "[" + sdf.format(new Date()) + "]"; } public static void main(String[] args) {