2011-11-08 9 views
14

これはシンプルな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!"); 
    } 
+1

コールソケット '近い()'メソッド。 http://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html –

+0

また、 'ServerSocket'コンストラクタがサーバをスローする場合に' close() 'を呼び出す前にヌルチェックが必要です。例外。 – unholysampler

+0

@Kit Ho、アプリケーションはどのように終了しましたか? – mre

答えて

0

最終的には実行されませんでしたか?おそらく、(真の)中には、代わりにあなたが

+0

ちょっとしたメモ、Javadocをチェックしてください。あなたは破壊しないで、閉じたいです。 http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html –

+0

はそれを手に入れませんでしたが、もっと詳しく説明できますか? –

+0

あなたは試してみることができます、メッセージ "サーバはシャットダウンされませんでした!" –

0

さて、どのようにあなたが「出口」プログラム近いソケットを扱うシャットダウンフックを作成することができます

while (!shutdownRequested) 

のようなものに置き換える必要がありますか? finallyは、例外がスローされるか、tryブロックが "通常"の方法で実行を終了した場合に実行されますが、while(true)のために "ハード"と思われます。

ソケットを閉じるにはsocket.close()を使用してください。破棄機能に頼らないことをお勧めします。

10

あなたのServerSocketを作成した後、あなたはJVMの終了時に、それを閉じるためにを追加することができ、このような何か:ServerSocket#closeを起動

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

は、SocketExceptionがをスローさせる、ブロックServerSocket.accept通話を終了します。ただし、whileループでのIOExceptionの現在の処理は、閉じたソケットでacceptを試行するためにwhileループに再入力することを意味します。 JVMはやはり終了しますが、ちょっと不安です。

コンソールアプリケーションをEclipseで終了するとシャットダウンフックが実行されません(Windowsでは少なくとも)。しかし、通常のコンソールでCTRL-C Javaを実行すると実行されます。それらを実行するには、JVMを正常に終了する必要があります。 SIGKILLではなくSIGINTまたはSIGTERM(kill -9)。

Eclipseやコンソールで実行できる簡単なプログラムがこれを実証します。

+1

'ShutDownHook'はいつも実行されていますか?それらに頼るのは一般的で安全な習慣ですか? – Gevorg

+1

@Gevorg javadocによれば、シャットダウンフックはJVMが正常に終了したときに終了する前にJVMによって実行されます。 Javaプロセスを "kill -9"した場合、Javaプロセスは終了しません。商用エンタープライズソフトウェアのサーバープロセスを正常にシャットダウンするためにシャットダウンフックが確実に使用されています。 – sudocode

+0

彼の問題は 'finally {}'ブロックへの 'accept()'ループから抜け出してしまいました。 – EJP

7

オペレーティングシステムは、プログラムが終了すると、すべてのTCPソケットを閉じます。

+4

プログラムが終了するとOSがすべてのTCPソケットを閉じますが、すべての場合に*「必要はない」と言います。このプログラムを終了する前にリッスンポートを解放する必要があるかどうかによって異なります(ただし、この場合は、OPがプログラムを終了するとOPが終了するのでOKです) – xav

2

javadocから:

彼らがしよう - と、リソース文で を作成されているので、Javaランタイムは自動的に、入力および出力ストリームを閉じ クライアントソケット、およびサーバソケット。プログラムは、プログラムにと リリースリソースをクリーンアップする機会を与えることを終了する前に

はまた

finalize()方法は、Java仮想マシン(JVM) によって呼び出されます。マルチスレッドプログラムはすべてのファイルを閉じて、終了する前に使用している ソケットを使用して、リソースがなくなってしまいます。 starvation。finalize()メソッドのserver.close()への呼び出しは、 このプログラムの各スレッドで使用されるソケット接続を閉じます。 finallyブロック、あるいは今のJava 7であなたがしよう - と、リソースブロックを使用することができ、そしてそれはあなたのためにそれらを閉じますあなたの中

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); 
    } 
    } 
関連する問題