001package var.sockets.tcp.echo;
002
003import java.io.BufferedReader;
004import java.io.IOException;
005import java.io.InputStreamReader;
006import java.io.PrintWriter;
007import java.net.ServerSocket;
008import java.net.Socket;
009import java.net.SocketAddress;
010import java.util.concurrent.Executor;
011import java.util.concurrent.Executors;
012
013/**
014 * threaded server for var.sockets.tcp.echo Echo service. waits for the next
015 * client to connect, creates thread and handles connection in concurrently:
016 * sends greeting message to client, reads line by line from client and sends it
017 * back adding "echo: " in front of each line until connection is closed by
018 * client.
019 *
020 * @author Sandro Leuchter
021 *
022 */
023public class EchoServerThreadPool {
024        /**
025         * port on which this service is currently listening on localhost
026         */
027        private final int port;
028        /**
029         * thread pool of this server
030         */
031        private final Executor threadPool;
032
033        /**
034         * the only constructor for this class
035         *
036         * @param port port on which this service will be listening on localhost
037         */
038        public EchoServerThreadPool(int port) {
039                this.port = port;
040                // threadPool = Executors.newSingleThreadExecutor();
041                // threadPool = Executors.newCachedThreadPool();
042                this.threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
043        }
044
045        /**
046         * creates server socket on localhost:port, infinitely handles connections to
047         * clients concurrently
048         */
049        public void start() {
050                try (ServerSocket serverSocket = new ServerSocket(this.port)) {
051                        System.out.println("EchoServer (threaded) auf " + serverSocket.getLocalSocketAddress() + " gestartet ...");
052                        while (true) {
053                                Socket socket = serverSocket.accept();
054                                this.threadPool.execute(new EchoThread(socket));
055                        }
056                } catch (IOException e) {
057                        System.err.println(e);
058                }
059        }
060
061        /**
062         * Each connection is handled with an instance of this class.
063         */
064        private class EchoThread implements Runnable {
065                /**
066                 * TCP connection to client
067                 */
068                private final Socket socket;
069
070                /**
071                 * the only constructor for this class
072                 *
073                 * @param socket the individual socket that the server created on accepting a
074                 *               client that this EchoThread instance will be communicating with
075                 */
076                public EchoThread(Socket socket) {
077                        this.socket = socket;
078                }
079
080                /**
081                 * defines the behavior of this Thread instance, will be executed concurrently
082                 * if start() is called on instance
083                 *
084                 */
085                @Override
086                public void run() {
087                        SocketAddress socketAddress = this.socket.getRemoteSocketAddress();
088                        System.out.println("Verbindung zu " + socketAddress + " aufgebaut");
089                        try (BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
090                                        PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true)) {
091                                out.println("Server ist bereit ...");
092                                String input;
093                                while ((input = in.readLine()) != null) {
094                                        System.out.println(socketAddress + ">> [" + input + "]");
095                                        out.println("echo: " + input);
096                                }
097                        } catch (Exception e) {
098                                System.err.println(e);
099                        } finally {
100                                System.out.println("Verbindung zu " + socketAddress + " abgebaut");
101                        }
102                }
103        }
104
105        /**
106         * main method: entrypoint to run service
107         *
108         * @param args args[0] must be the port number of the server (int); rest of args
109         *             is ignored
110         */
111        public static void main(String[] args) {
112                int port = Integer.parseInt(args[0]);
113                new EchoServerThreadPool(port).start();
114        }
115}