InDaPond
InDaPond

Reputation: 572

Threaded Server stuck on accept() AKA How to shutdown a MulThreaded Server via client input?

Since I am stuck for this for a week now and still haven't firgured it out I try to express what I want as cleary as possible.

I have a Server which can handle Multiple Clients and communicates with them. Whenever a client connects, the server passes the Client's request to my class RequestHandler, in which the clients commands are being processed. If one of the clients says "SHUTDOWN", the server is supposed to cut them loose and shut down. It doesn't work. If only one client connects to the server, the server seems to be stuck in the accept() call and I do not know how to fix this.

THERE is already one response, but please do not take note of it, it was on a different topic which is outdated

I have two approaches and both don't seem to work. 1)If the client writes "SHUTDOWN", the shutdownFlag is set to true (in hope to exit the while loop) 2)If the client writes "SHUTDOWN", the static method shutdown() is called on the Server, which should shut him down

Below you see the implementation of my Server class, the other two classes involved are Client(all he does is connect to the Socket) and RequestHandler (this class processes the Input and writes it) . I am 98% sure the problem lies within the Server class.

Below this is an even shorter version of the Server with just the methods without any Console outputs which might help understanding it in case you want to copy the code

public class Server {
    public static final int PORTNUMBER = 8540;
    public static final int MAX_CLIENTS = 3;
    public static boolean shutdownFlag = false;
    public static ExecutorService executor = null;
    public static ServerSocket serverSocket = null;

    public static void main(String[] args) {

        ExecutorService executor = null;
        try (ServerSocket serverSocket = new ServerSocket(PORTNUMBER);) {
            executor = Executors.newFixedThreadPool(MAX_CLIENTS);
            System.out.println("Waiting for clients");
            while (!shutdownFlag) {
                System.out.println("shutdown flag ist : " + shutdownFlag);          
                Socket clientSocket = serverSocket.accept();
                Runnable worker = new RequestHandler(clientSocket);
                executor.execute(worker);
                System.out.println("Hallo");

            }
            if (shutdownFlag) {
                System.out.println("Flag is on");               
                try {
                    executor.awaitTermination(10, TimeUnit.SECONDS);
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                 try {
                        //Stop accepting requests.
                        serverSocket.close();
                    } catch (IOException e) {
                        System.out.println("Error in server shutdown");
                        e.printStackTrace();
                    }
                serverSocket.close();
            }
            System.out.println("shutting down");
        } catch (IOException e) {
            System.out
                    .println("Exception caught when trying to listen on port "
                            + PORTNUMBER + " or listening for a connection");
            System.out.println(e.getMessage());
        } finally {
            if (executor != null) {
                executor.shutdown();
            }
        }
    }

    public static void shutdown(){
        if (shutdownFlag) {
            System.out.println("Flag is on");               
            try {
                executor.awaitTermination(10, TimeUnit.SECONDS);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
             try {
                    //Stop accepting requests.
                    serverSocket.close();
                } catch (IOException e) {
                    System.out.println("Error in server shutdown");
                    e.printStackTrace();
                }
            try {
                serverSocket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

public class Server {
    public static final int PORTNUMBER = 8540;
    public static final int MAX_CLIENTS = 3;
    public static boolean shutdownFlag = false;
    public static ExecutorService executor = null;
    public static ServerSocket serverSocket = null;

    public static void main(String[] args) {

        ExecutorService executor = null;
        try (ServerSocket serverSocket = new ServerSocket(PORTNUMBER);) {
            executor = Executors.newFixedThreadPool(MAX_CLIENTS);

            while (!shutdownFlag) {
                Socket clientSocket = serverSocket.accept();
                Runnable worker = new RequestHandler(clientSocket);
                executor.execute(worker);

            }
            if (shutdownFlag) {
                try {
                    executor.awaitTermination(10, TimeUnit.SECONDS);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                serverSocket.close();
            }
        } catch (IOException e) {
        } finally {
            if (executor != null) {
                executor.shutdown();
            }
        }
    }

    public static void shutdown() {
        if (shutdownFlag) {
            try {
                executor.awaitTermination(10, TimeUnit.SECONDS);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

Upvotes: 1

Views: 109

Answers (1)

Neil Locketz
Neil Locketz

Reputation: 4318

If you move the code in main into an instance method on Server (we'll say run here) you can just do new Server().run() inside main. That way you have an instance (this) to work with inside your run method. Something like this:

class Server {
     private boolean shutdownFlag = false; // This can't be static anymore.
     public static final Server SERVER = new Server();
     public static void main(String[] args) {
         SERVER.run();
     }
     private void run() {
         // Here goes everything that used to be inside main...
         // Now you have the Server.SERVER instance to use outside the class
         // to shut things down or whatever ...  
     }
}

This pattern isn't actually that great but better would be too long for here. Hopefully this gets you off to a good start.

Upvotes: 1

Related Questions