如何以正确的方式关闭插座?

Kit*_* Ho 17 java sockets tcp

这是一个简单的TCP服务器.程序终止后如何关闭套接字?我使用try/finally并尝试关闭套接字.但是当我退出程序时它不会运行finally块.

任何人都可以知道如何以正确的方式关闭插座?

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!");
    }
Run Code Online (Sandbox Code Playgroud)

sud*_*ode 12

在创建ServerSocket之后,您可以添加ShutdownHook以在JVM终止时关闭它,如下所示:

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

调用ServerSocket #close将终止阻塞的ServerSocket.accept调用,导致它抛出SocketException.但是,请注意,您在while循环中当前对IOException的处理意味着您将重新进入while循环以尝试在已关闭的套接字上接受.JVM仍将终止,但它有点凌乱.

如果在Eclipse中终止控制台应用程序(至少在Windows上),则不会运行关闭挂钩.但是如果您在普通控制台中使用CTRL-C Java,它们就会运行.要让它们运行,您需要正常终止JVM,例如SIGINT或SIGTERM而不是SIGKILL(kill -9).

您可以在Eclipse或控制台中执行的简单程序将证明这一点.

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @Gevorg正如Javadoc所说,ShutdownHooks由JVM运行,然后在正常终止时退出。如果您“杀死-9” Java进程,则不会。我已经看到关闭钩子可可靠地用于有序地关闭商业企业软件中的服务器进程。 (2认同)

art*_*tol 7

在您的特定情况下,操作系统将在程序退出时关闭所有TCP套接字.

  • 你说对,OS会在程序退出时关闭所有的TCP套接字,但在所有情况下我都不会说*"不需要"*.这取决于你是否需要在退出这个程序之前释放被监听的端口(虽然在这种情况下,它应该没问题,因为OP想要在程序退出时关闭它) (5认同)

Pet*_*nto 1

为什么最后没有运行?可能 while(true) 应该替换为类似的东西

while (!shutdownRequested)
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个关闭钩子来处理套接字关闭