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