From ad7bfe8eea5e469a78a4c13e3f66ac05f62eb4b6 Mon Sep 17 00:00:00 2001 From: Mihail Vasilev Date: Tue, 16 Dec 2025 11:37:06 +0300 Subject: [PATCH 1/3] feature: server now working --- .../java/io/github/winroot33/EchoServer.java | 22 +++++++++++ .../io/github/winroot33/EchoServerThread.java | 38 +++++++++++++++++++ src/main/java/io/github/winroot33/Main.java | 6 ++- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/github/winroot33/EchoServer.java create mode 100644 src/main/java/io/github/winroot33/EchoServerThread.java diff --git a/src/main/java/io/github/winroot33/EchoServer.java b/src/main/java/io/github/winroot33/EchoServer.java new file mode 100644 index 0000000..97a5144 --- /dev/null +++ b/src/main/java/io/github/winroot33/EchoServer.java @@ -0,0 +1,22 @@ +package io.github.winroot33; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +public class EchoServer { + + public void start(int portNumber) throws IOException { + + try (ServerSocket serverSocket = new ServerSocket(portNumber)) { + System.out.println("Server started"); + while (true) { + Socket clientSocket = serverSocket.accept(); + var serverThread = new EchoServerThread(clientSocket); + serverThread.start(); + + System.out.printf("Thread: %s started\n",serverThread.getName()); + } + } + } +} diff --git a/src/main/java/io/github/winroot33/EchoServerThread.java b/src/main/java/io/github/winroot33/EchoServerThread.java new file mode 100644 index 0000000..7053079 --- /dev/null +++ b/src/main/java/io/github/winroot33/EchoServerThread.java @@ -0,0 +1,38 @@ +package io.github.winroot33; + +import lombok.RequiredArgsConstructor; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.Socket; + +@RequiredArgsConstructor +public class EchoServerThread extends Thread { + + private final Socket clientSocket; + + @Override + public void run() { + try (PrintWriter out = new PrintWriter(clientSocket.getOutputStream()); + BufferedReader in = new BufferedReader( + new InputStreamReader(clientSocket.getInputStream()))) { + + String inputLine; + while ((inputLine = in.readLine()) != null) { + out.println(inputLine); + System.out.printf("Thread: %s\tMessage sent: %s\n", Thread.currentThread().getName(), inputLine); + } + } catch (IOException e) { + System.err.println("IO Error: " + e.getMessage()); + } finally { + try { + clientSocket.close(); + } catch (IOException e) { + System.err.println("Error closing socket: " + e.getMessage()); + } + } + + } +} diff --git a/src/main/java/io/github/winroot33/Main.java b/src/main/java/io/github/winroot33/Main.java index 94eaa94..98c9f1a 100644 --- a/src/main/java/io/github/winroot33/Main.java +++ b/src/main/java/io/github/winroot33/Main.java @@ -1,6 +1,10 @@ package io.github.winroot33; +import java.io.IOException; + public class Main { - public static void main(String[] args) { + public static void main(String[] args) throws IOException { + EchoServer server = new EchoServer(); + server.start(23); } } \ No newline at end of file From 1eb3d4f8b15964f3005d7bd2920b200117f04d9a Mon Sep 17 00:00:00 2001 From: Mihail Vasilev Date: Tue, 16 Dec 2025 12:11:42 +0300 Subject: [PATCH 2/3] refactor: added thread pool --- .../winroot33/ClientConnectionHandler.java | 53 +++++++++++++++++++ .../github/winroot33/ConnectionExecutor.java | 46 ++++++++++++++++ .../java/io/github/winroot33/EchoServer.java | 31 ++++++++--- .../io/github/winroot33/EchoServerThread.java | 38 ------------- src/main/java/io/github/winroot33/Main.java | 4 +- 5 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 src/main/java/io/github/winroot33/ClientConnectionHandler.java create mode 100644 src/main/java/io/github/winroot33/ConnectionExecutor.java delete mode 100644 src/main/java/io/github/winroot33/EchoServerThread.java diff --git a/src/main/java/io/github/winroot33/ClientConnectionHandler.java b/src/main/java/io/github/winroot33/ClientConnectionHandler.java new file mode 100644 index 0000000..bfda7ac --- /dev/null +++ b/src/main/java/io/github/winroot33/ClientConnectionHandler.java @@ -0,0 +1,53 @@ +package io.github.winroot33; + +import lombok.RequiredArgsConstructor; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.Socket; +import java.nio.charset.StandardCharsets; + +/** + * Класс для обработки соединений с клиентами, Runnable для передачи в пул потоков + */ +@RequiredArgsConstructor +public class ClientConnectionHandler implements Runnable { + private final Socket clientSocket; + + @Override + public void run() { + handleConnection(); + } + + /** + * Обработка нового соединения + */ + private void handleConnection() { + try (Socket socket = this.clientSocket; + PrintWriter out = new PrintWriter(socket.getOutputStream(), true, StandardCharsets.UTF_8); + BufferedReader in = new BufferedReader( + new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))) { + + processClientMessages(in, out); + + } catch (IOException e) { + System.err.println("IO Error: " + e.getMessage()); + } + } + + /** + * Метод для отправки эхо сообщений пользователю + * + * @param in входной поток данных + * @param out выходной поток + */ + private void processClientMessages(BufferedReader in, PrintWriter out) throws IOException { + String inputLine; + while ((inputLine = in.readLine()) != null) { + out.println(inputLine); + System.out.printf("Thread: %s\tMessage sent: %s\n", Thread.currentThread().getName(), inputLine); + } + } +} diff --git a/src/main/java/io/github/winroot33/ConnectionExecutor.java b/src/main/java/io/github/winroot33/ConnectionExecutor.java new file mode 100644 index 0000000..9fb7927 --- /dev/null +++ b/src/main/java/io/github/winroot33/ConnectionExecutor.java @@ -0,0 +1,46 @@ +package io.github.winroot33; + +import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * Обертка над ExecutorService для удобного создания новых соединений с клиентами + */ +public class ConnectionExecutor { + private final ExecutorService threadPool; + + /** + * Создание пула потоков с указанным количеством + * + * @param maxConnections количество потоков для FixedThreadPool + */ + public ConnectionExecutor(int maxConnections) { + this.threadPool = Executors.newFixedThreadPool(maxConnections); + } + + /** + * Обработка подключения нового клиента, создание и отправка задачи в ExecutorService + * + * @param clientSocket сокет с соединением нового клиента + */ + public void executeConnection(Socket clientSocket) { + Runnable connectionHandler = new ClientConnectionHandler(clientSocket); + threadPool.execute(connectionHandler); + } + + /** + * Корректная остановка пула потоков + */ + public void shutdownGracefully() { + threadPool.shutdown(); + try { + if (!threadPool.awaitTermination(30, TimeUnit.SECONDS)) { + threadPool.shutdownNow(); + } + } catch (InterruptedException e) { + threadPool.shutdownNow(); + } + } +} diff --git a/src/main/java/io/github/winroot33/EchoServer.java b/src/main/java/io/github/winroot33/EchoServer.java index 97a5144..ac06306 100644 --- a/src/main/java/io/github/winroot33/EchoServer.java +++ b/src/main/java/io/github/winroot33/EchoServer.java @@ -4,19 +4,38 @@ import java.net.ServerSocket; import java.net.Socket; +/** + * Класс для запуска эхо сервера + */ public class EchoServer { - public void start(int portNumber) throws IOException { + private final ConnectionExecutor connectionExecutor; + private final int port; - try (ServerSocket serverSocket = new ServerSocket(portNumber)) { + /** + * Создание эхо сервера + * + * @param port номер порта для сервера + * @param maxConnections количество потоков для FixedThreadPool + */ + public EchoServer(int port, int maxConnections) { + this.port = port; + this.connectionExecutor = new ConnectionExecutor(maxConnections); + } + + /** + * Запуск эхо сервера + */ + public void start() throws IOException { + + try (ServerSocket serverSocket = new ServerSocket(port)) { System.out.println("Server started"); while (true) { Socket clientSocket = serverSocket.accept(); - var serverThread = new EchoServerThread(clientSocket); - serverThread.start(); - - System.out.printf("Thread: %s started\n",serverThread.getName()); + connectionExecutor.executeConnection(clientSocket); } + } finally { + connectionExecutor.shutdownGracefully(); } } } diff --git a/src/main/java/io/github/winroot33/EchoServerThread.java b/src/main/java/io/github/winroot33/EchoServerThread.java deleted file mode 100644 index 7053079..0000000 --- a/src/main/java/io/github/winroot33/EchoServerThread.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.winroot33; - -import lombok.RequiredArgsConstructor; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.net.Socket; - -@RequiredArgsConstructor -public class EchoServerThread extends Thread { - - private final Socket clientSocket; - - @Override - public void run() { - try (PrintWriter out = new PrintWriter(clientSocket.getOutputStream()); - BufferedReader in = new BufferedReader( - new InputStreamReader(clientSocket.getInputStream()))) { - - String inputLine; - while ((inputLine = in.readLine()) != null) { - out.println(inputLine); - System.out.printf("Thread: %s\tMessage sent: %s\n", Thread.currentThread().getName(), inputLine); - } - } catch (IOException e) { - System.err.println("IO Error: " + e.getMessage()); - } finally { - try { - clientSocket.close(); - } catch (IOException e) { - System.err.println("Error closing socket: " + e.getMessage()); - } - } - - } -} diff --git a/src/main/java/io/github/winroot33/Main.java b/src/main/java/io/github/winroot33/Main.java index 98c9f1a..40ffc7c 100644 --- a/src/main/java/io/github/winroot33/Main.java +++ b/src/main/java/io/github/winroot33/Main.java @@ -4,7 +4,7 @@ public class Main { public static void main(String[] args) throws IOException { - EchoServer server = new EchoServer(); - server.start(23); + EchoServer server = new EchoServer(23, 10); + server.start(); } } \ No newline at end of file From 8c271fe9a24ed8d4f09efd0010ad9e8dbfb9ccde Mon Sep 17 00:00:00 2001 From: Mihail Vasilev Date: Tue, 16 Dec 2025 12:23:50 +0300 Subject: [PATCH 3/3] fix: port changed to 7, as in rfc --- src/main/java/io/github/winroot33/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/winroot33/Main.java b/src/main/java/io/github/winroot33/Main.java index 40ffc7c..8fc7d2d 100644 --- a/src/main/java/io/github/winroot33/Main.java +++ b/src/main/java/io/github/winroot33/Main.java @@ -4,7 +4,7 @@ public class Main { public static void main(String[] args) throws IOException { - EchoServer server = new EchoServer(23, 10); + EchoServer server = new EchoServer(7, 10); server.start(); } } \ No newline at end of file