¿Cómo puedo cerrar el enchufe de forma adecuada? [duplicar]

This is a simple TCP server. How can i close the socket when the program is terminated? I have using try/finally and try to close the socket. But it doesn't run the finally block when I exit the program.

Anyone can have idea on how to close the socket in a proper way?

try {
        socket = new ServerSocket(port);
        System.out.println("Server is starting on port " + port + " ...");
    }catch (IOException e){
        System.out.println("Error on socket creation!");
    }

    Socket connectionSocket = null;
    try{
        while(true){            
            try{
                connectionSocket = socket.accept();
                Thread t =  new Thread(new ClientConnection(connectionSocket));
                t.start();
            }catch (IOException e) {
                System.out.println("Error on accept socket!");
            }
        }
    }finally{
        this.socket.close();
        System.out.println("The server is shut down!");
    }

preguntado el 08 de noviembre de 11 a las 14:11

call the sockets close() method in your finally block, or now with java 7 you can use the try-with-resources block, and it will close them for you. javacodegeeks.com/2011/07/… -

You also need a null check before calling close() en caso de que el ServerSocket constructor throws an exception. -

@mre: just by pressing the terminate button in eclipse or control-c in console. I wanna add a final msg saying "the server is shut down", in python, it is easy to do that, but don't know in java -

I would catch IOException outside your loop. It is highly unlikely you can recover from this error so looping infinitely might not be a good idea. -

@Peter Lawrey +1, or else add a break en el bloque de captura. -

5 Respuestas

After creating your ServerSocket, you could add a ShutdownHook to close it on JVM termination, something like this:

Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){
    try {
        socket.close();
        System.out.println("The server is shut down!");
    } catch (IOException e) { /* failed */ }
}});

Invocando ServerSocket#close will terminate the blocking ServerSocket.accept call, causing it to throw a SocketException. However, note that your current handling of IOException in the while loop means you will then re-enter the while loop to attempt accept on a closed socket. The JVM will still terminate, but it's a bit untidy.

Shutdown hooks do not run if you terminate a console application in Eclipse (on Windows at least). But they do run if you CTRL-C Java in a normal console. For them to run, you need the JVM to be terminated normally, e.g. SIGINT or SIGTERM rather than SIGKILL (kill -9).

A simple program which you can execute in Eclipse or a console will demonstrate this.

public class Test implements Runnable {

  public static void main(String[] args) throws InterruptedException {
    final Test test = new Test();
    Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){
      test.shutdown();
    }});
    Thread t = new Thread(test);
    t.start();
  }

  public void run() {
    synchronized(this) {
      try {
        System.err.println("running");
        wait();
      } catch (InterruptedException e) {}
    }
  }

  public void shutdown() {
    System.err.println("shutdown");
  }
}

Respondido 09 Oct 14, 12:10

sí hay ShutDownHooks ALWAYS executed? Is it a common and safe practice to rely on those? - Marsellus Wallace

@Gevorg As the javadoc says, ShutdownHooks are run by the JVM before exiting when it is terminated normally. If you "kill -9" a Java process, they will not. I have seen shutdown hooks used reliably for orderly shutdown of server processes in commercial enterprise software. - sudocode

His problem is getting out of the accept() bucle en el finally{} block, not what to do once he gets there. - user207421

@EJP That's partly true - the ShutdownHook provides a way to interrupt socket.accept() on JVM termination, but the current handling of IOException (and by extension SocketException) in the while loop defeats that. However, my answer does not address the finally block at all. The OP was mistaken to think that finally should be run on JVM termination. - sudocode

@sudocode Shutdown hooks are not part of the solution of this problem. He doesn't need to close the socket on termination. The OS will do that for him. His problem is that the finally }{} block isn't executed so he never sees his message, so he piensa his socket isn't closed. - user207421

No need in your particular case, the operating system will close all the TCP sockets for you when the program exits.

Respondido 05 ago 17, 14:08

You're right saying that OS will close all the TCP sockets when the program exits, but I wouldn't say "No need" in all cases. It depends if you need to release the listened port before exiting this program (though in this case, it should be OK since the OP wants to close it when program exits) - xav

Desde javadoc :

The Java runtime automatically closes the input and output streams, the client socket, and the server socket because they have been created in the try-with-resources statement.

También

La Certificación de Catequista de finalize() method is called by the Java virtual machine (JVM) before the program exits to give the program a chance to clean up and release resources. Multi-threaded programs should close all Files and Sockets they use before exiting so they do not face resource starvation. The call to server.close() en el objeto finalize() method closes the Socket connection used by each thread in this program.

protected void finalize(){
//Objects created in run method are finalized when
//program terminates and thread exits
     try{
        server.close();
    } catch (IOException e) {
        System.out.println("Could not close socket");
        System.exit(-1);
    }
  }

contestado el 04 de mayo de 15 a las 03:05

Howcome the finally is not run? Probably the while(true) should be replaced with something like

while (!shutdownRequested)

alternatively you can create a shutdown hook that handles the socket close

respondido 08 nov., 11:18

a nit-picky note, check out the Javadoc. You want to close, not destroy. download.oracle.com/javase/6/docs/api/java/net/… - Daniel B. Chapman

didn't get it, can u elaborate more? - Kit Ho

you can try, the Message "The server is shut down would not print!" - Kit Ho

Well, how do you "exit" the program? finally will be executed if an exception will be thrown or if the try block finishes its execution in a "normal" way but I think that might be "hard" because of your while(true).

To close the socket you should use socket.close() and I would recommend you not to rely on the destroy function.

respondido 08 nov., 11:18

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.