web-dev-qa-db-ja.com

適切な方法でソケットを閉じるにはどうすればよいですか?

これは単純なTCPサーバーです。プログラムが終了したときにソケットを閉じるにはどうすればよいですか?try/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!");
    }
16
Kit Ho

ServerSocketを作成した後、JVM終了時に ShutdownHook を追加して、次のように追加できます。

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を実行した場合は実行されます。実行するには、SIGKILLではなくSIGINTまたはSIGTERM(kill -9)など、JVMを正常に終了する必要があります。

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

特定のケースでは必要ありません。オペレーティングシステムは、プログラムの終了時にすべてのTCPソケットを閉じます。

7
artbristol

javadoc から:

Javaランタイムは、try-with-resourcesステートメントで作成されているため、入力および出力ストリーム、クライアントソケット、およびサーバーソケットを自動的に閉じます。

また

finalize()メソッドは、プログラムがリソースをクリーンアップおよび解放する機会を与えるために、プログラムが終了する前にJava仮想マシン(JVM)]によって呼び出されます。リソースの枯渇に直面しないように、終了する前に使用するすべてのファイルとソケットserver.close()メソッドでfinalize()を呼び出すと、このプログラムの各スレッドで使用されているソケット接続が閉じられます。

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);
    }
  }
2
MChaker

最終的に実行されない方法は?おそらくwhile(true)は次のようなものに置き換える必要があります

while (!shutdownRequested)

代わりに、ソケットのクローズを処理するシャットダウンフックを作成できます

1
Peter Szanto

さて、どのようにしてプログラムを「終了」しますか? finallyは、例外がスローされる場合、またはtryブロックが「通常の」方法で実行を終了する場合に実行されますが、while(true)のために「ハード」であると思います。

ソケットを閉じるには、socket.close()を使用する必要があります。destroy関数に依存しないことをお勧めします。

0