How to break an infinite loop using Ctrl-C in Java

1

I have a multithreaded server that sits in an infinite loop waiting for new connections and I want to be able to stop this loop when I press Ctrl-C (or something similar). I tried this solution and tried to do something like this:

private void waitForConnections() {
    boolean done = false;
    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            super.run();
            System.err.println("Exiting");
            done = true;
        }
    });

    while (!done) {
        try {
            Socket userSocket = this.serverSocket.accept();
            // Faz alguma coisa...
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

But I can not change the value of the done done variable inside the thread. How can I solve this problem in the simplest and most elegant way?

    
asked by anonymous 12.04.2018 / 18:00

2 answers

0

I got a temporary solution while others did not show up. What I did was just replace the ShutdownHook with a Thread normal and inside the method run I made an infinite loop that reads the user input and stops when it enters end of file (Ctrl + D in the MAC). But I'm still not satisfied with this solution ... it seems to me gambiarra.

Here's my code:

private void waitForConnections() {
    new Thread(this).start();

    try {
        //noinspection InfiniteLoopStatement
        while (true) {
            Socket userSocket = this.serverSocket.accept();
            allocateClient(userSocket);
        }
    } catch (IOException e) {
        // The user socket was closed by the shutdown method, so, no need for printing the stack trace.
        //e.printStackTrace();
    }
}

@Override
public void run() {
    Scanner s = new Scanner(System.in);
    while (s.hasNext())
        s.nextLine();

    shutdown();
}

The shutdown method closes ServerSocket by generating IOException within the loop.

    
13.04.2018 / 19:15
-1

I did a minimal and functional example of the StackOverflow site. In my example, I did not need to add a finalizing hook. The operation is very simple, a Thread has been created to be the Application Listener and another Handler to handle the clients. I do not know if it is the ideal solution for your problem and you should certainly have problems.

import java.io.PrintWriter;

import java.net.Socket;
import java.net.ServerSocket;

import java.util.concurrent.TimeUnit;

public class Teste {

    static class Listener extends Thread {

        public void run() {
            try (ServerSocket ss = new ServerSocket(10113)){
                System.out.println("Iniciei servidor");
                while(true) {
                    try {
                        System.out.println("Esperando cliente");
                        Handler handler = new Handler(ss.accept());
                        handler.start();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                System.exit(-1);
            }

        }

    };

    static class Handler extends Thread {

        Socket client;

        public Handler(Socket client) {
            this.client = client;
        }

        public void run() {
            try (PrintWriter writer = new PrintWriter(client.getOutputStream(), true)) {
                writer.println("meu super teste");
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                if (client != null) {
                    try {
                        client.close();
                    } catch (Exception ex) {
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Teste.Listener listener = new Teste.Listener();
        listener.setDaemon(true);
        listener.start();
        try {
            System.out.println("esperando servidor iniciar");
            TimeUnit.SECONDS.sleep(30);
        } catch (Exception ex) {}
    }

}
    
13.04.2018 / 20:48