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}