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

2022-09-02 10:02:49

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

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

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!");
    }

答案 1

创建 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 */ }
}});

调用 ServerSocket#close 将终止阻塞 ServerSocket.accept 调用,从而导致它引发 SocketException。但是,请注意,您当前在 while 循环中对 IOException 的处理意味着您将重新进入 while 循环以尝试在闭合套接字上接受。JVM 仍将终止,但它有点不整洁。

如果在 Eclipse 中终止控制台应用程序(至少在 Windows 上),则关闭挂钩不会运行。但是如果你在普通控制台中CTRL-C Java,它们确实会运行。为了让它们运行,你需要JVM正常终止,例如SIGINT或SIGTERM而不是SIGKILL(杀死-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");
  }
}

答案 2

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


推荐