Package mypackage

Source Code of mypackage.ConnectionProcessor

package mypackage;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MultiThreadedServer {
    public static final int DEFAULT_FINISH_AWAIT_TIMEOUT = 5;
    private ExecutorService threadPoolExecutor = Executors.newCachedThreadPool();
    private ServerSocketChannel server;
    private boolean isRunning;
    private volatile int finishAwaitTimeout = DEFAULT_FINISH_AWAIT_TIMEOUT;

    public MultiThreadedServer(int port) throws IOException {
        server = ServerSocketChannel.open();
        server.bind(new InetSocketAddress(port));
        server.configureBlocking(false);
    }

    public int getPort() {
        return server.socket().getLocalPort();
    }

    public InetAddress getAddress() {
        return server.socket().getInetAddress();
    }

    public boolean isRunning() {
        return isRunning;
    }

    public synchronized void start() {
        if (isRunning) return;
        isRunning = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (isRunning) {
                        SocketChannel client = server.accept();
                        if (client == null) continue;
                        System.out.println("Connection from " + client.socket().getInetAddress());
                        threadPoolExecutor.execute(new ConnectionProcessor(client));
                    }
                } catch (IOException e) {
                    System.err.println("Error while accepting connections");
                    e.printStackTrace();
                } finally {
                    System.out.println("Server is shutting down...");
                    System.out.println("Waiting remaining connection processors to terminate...");
                    try {
                        threadPoolExecutor.shutdown();
                        if(!threadPoolExecutor.awaitTermination(finishAwaitTimeout, TimeUnit.SECONDS)) {
                            System.err.println("Timeout has been exceeded\nForce terminating execution...");
                            threadPoolExecutor.shutdownNow();
                            if (!threadPoolExecutor.awaitTermination(finishAwaitTimeout, TimeUnit.SECONDS)) {
                                System.err.println("Pool has failed to terminate");
                            }
                        }
                    } catch (InterruptedException e) {
                        System.err.println("The threadPoolExecutor has been interrupted");
                        e.printStackTrace();
                    } finally {
                        try {
                            server.close();
                        } catch (IOException e) {
                            System.err.println("Error while closing the socket");
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, "The server's main thread").start();
        System.out.println("The server is now running...");
    }

    public synchronized void stop() {
        isRunning = false;
    }

    public int getFinishAwaitTimeout() {
        return finishAwaitTimeout;
    }

    public void setFinishAwaitTimeout(int finishAwaitTimeout) {
        this.finishAwaitTimeout = finishAwaitTimeout;
    }

    public static void main(String[] args) throws IOException {
        final MultiThreadedServer server = new MultiThreadedServer(8080);
        server.start();
        for (int i = 0; i < 500; ++i) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try(SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(8080))) {
                        socketChannel.configureBlocking(false);
                        ByteBuffer buf = ByteBuffer.wrap("Hello from a client".getBytes());
                        while (buf.hasRemaining()) {
                            socketChannel.write(buf);
                        }
                        buf = ByteBuffer.allocate(128);
                        Charset charset = Charset.forName(System.getProperty("file.encoding"));
                        StringBuilder builder = new StringBuilder();
                        while (socketChannel.read(buf) != -1) {
                            buf.flip();
                            builder.append(charset.decode(buf));
                            buf.clear();
                        }
                        System.out.println("Server response: " + builder.toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                new Scanner(System.in).nextLine();
                server.stop();
            }
        }).start();
    }
}

class ConnectionProcessor implements Runnable {
    private volatile static long numOfCons = 0;
    private SocketChannel sock;
    private long numOfCon;

    public ConnectionProcessor(SocketChannel sock) {
        this.sock = sock;
        this.numOfCon = ++numOfCons;
    }

    @Override
    public void run() {
        ByteBuffer buffer = ByteBuffer.allocate(128);
        Charset charset = Charset.forName(System.getProperty("file.encoding"));
        StringBuilder builder = new StringBuilder();
        try {
            sock.configureBlocking(false);
            while(sock.read(buffer) > 0) {
                buffer.flip();
                builder.append(charset.decode(buffer));
                buffer.clear();
            }
            System.out.printf("From client #%d:\n%s\n", numOfCon, builder.toString());
            String respBody = "<html>" +
                    "<body>Hello, world</body>" +
                    "</html>";
            String respHead = String.format("HTTP/1.1 200 OK\n" +
                    "Content-Type: text/html; charset=utf-8\n" +
                    "Content-Length: %d\n\n", respBody.getBytes().length);
            buffer = ByteBuffer.wrap(respBody.getBytes());
            ByteBuffer headBuffer = ByteBuffer.wrap(respHead.getBytes());
            ByteBuffer[] bufAr = {headBuffer, buffer};
            sock.write(bufAr);
        } catch (IOException e) {
            System.err.println("Error while processing the connection #" + numOfCon);
            e.printStackTrace();
        } finally {
            try {
                sock.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
TOP

Related Classes of mypackage.ConnectionProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.