001package var.sockets.tcp.filer;
002
003import java.io.BufferedReader;
004import java.io.File;
005import java.io.FileReader;
006import java.io.IOException;
007import java.io.PrintWriter;
008import java.net.ServerSocket;
009import java.net.Socket;
010import java.net.SocketAddress;
011import java.util.concurrent.Executor;
012import java.util.concurrent.Executors;
013
014/**
015 * threaded server for var.sockets.tcp.filer File service. waits for clients to
016 * connect. Upon connection sends concurrently to other client connections a
017 * manually defined file back to client. closes the connection directly
018 * afterwards.
019 *
020 * @author Sandro Leuchter
021 *
022 */
023public class FileServerThreadPool {
024        /**
025         * path to file which will be sent to clients; relative to current working
026         * directory (e.g. project root)
027         */
028        private static final String FILE = "bin/var/sockets/tcp/filer/message.txt";
029        /**
030         * port on which this service is currently listening on localhost
031         */
032        private final int port;
033        /**
034         * thread pool of this server
035         */
036        private final Executor threadPool;
037
038        /**
039         * the only constructor for this class
040         *
041         * @param port port on which this service will be listening on localhost
042         */
043        public FileServerThreadPool(int port) {
044                this.port = port;
045                this.threadPool = Executors.newSingleThreadExecutor();
046                // threadPool = Executors.newCachedThreadPool();
047                // threadPool =
048                // Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2);
049        }
050
051        /**
052         * creates server socket on localhost:port, infinitely handles connections to
053         * clients concurrently
054         */
055        public void start() {
056                try (ServerSocket serverSocket = new ServerSocket(this.port)) {
057                        System.out.println("FileServer (threaded) auf " + serverSocket.getLocalSocketAddress() + " gestartet ...");
058                        File file = new File(FILE);
059                        if (file.exists()) {
060                                System.out.println("\"" + file.getAbsolutePath() + "\" soll gesendet werden.");
061                                while (true) {
062                                        Socket socket = serverSocket.accept();
063                                        this.threadPool.execute(new FileThread(socket));
064                                }
065                        }
066                } catch (IOException e) {
067                        System.err.println(e);
068                }
069        }
070
071        /**
072         * Each connection is handled with an instance of this class.
073         */
074        private class FileThread implements Runnable {
075                /**
076                 * TCP connection to client
077                 */
078                private final Socket socket;
079
080                /**
081                 * the only constructor for this class
082                 *
083                 * @param socket the individual socket that the server created on accepting a
084                 *               client that this EchoThread instance will be communicating with
085                 */
086                public FileThread(Socket socket) {
087                        this.socket = socket;
088                }
089
090                /**
091                 * defines the behavior of this Thread instance, will be executed concurrently
092                 * if start() is called on instance
093                 *
094                 */
095                @Override
096                public void run() {
097                        SocketAddress socketAddress = null;
098                        try (BufferedReader in = new BufferedReader(new FileReader(FILE));
099                                        PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true)) {
100                                socketAddress = this.socket.getRemoteSocketAddress();
101                                System.out.println("Verbindung zu  " + socketAddress + " aufgebaut");
102                                // Inhalt von in zeilenweise an out senden:
103                                System.out.println("Übertragung zu " + socketAddress + " begonnen");
104                                String input;
105                                while ((input = in.readLine()) != null) {
106                                        out.println(input);
107                                        // Thread.sleep(1000);
108                                }
109                                System.out.println("Übertragung zu " + socketAddress + " beendet");
110                        } catch (Exception e) {
111                                System.err.println(e);
112                        } finally {
113                                System.out.println("Verbindung zu  " + socketAddress + " abgebaut");
114                        }
115                }
116        }
117
118        /**
119         * main method: entrypoint to run service
120         *
121         * @param args args[0] must be the port number of the server (int); rest of args
122         *             is ignored
123         */
124        public static void main(String[] args) {
125                int port = Integer.parseInt(args[0]);
126                new FileServerThreadPool(port).start();
127        }
128}