2009-10-02 11 views
6

私はこのコードを使用してサーバのスレッドを持っている:ServerSocket.accept()でブロックされたスレッドのブロックを解除するには?

public void run() { 
    try { 
     ServerSocket server; 
     EneaLog.printLog("Server is running."); 
     server = new ServerSocket(this.portnumber); 

     while (true) { 
      new EneaServerConnection(server.accept(), this.project,stopped).start(); 
      if (stopped) { 
       EneaLog.printLog("Server safe-shutdown completed."); 
       EneaLog.printLog("Hi!"); 
       server.close(); 
       return; 
      } 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex); 
     project.getExceptionHandler().handler(ex); 
    } 
} 

と、このようなシャットダウン方法:

public void shutdown() { 
    EneaLog.printLog("Server shutdown NOW!"); 
    stopped = true; 
} 

私はシャットダウンがserver.accept(上で待機しているスレッドのブロックを解除することができますしたい)そう私はサーバーのシャットダウン前に接続を待機する必要があります。

シャットダウン()でserver.close()を実行できません。登録されているクライアントに、そのサーバがダウンしていることを通知する必要があるためです。

アイデア?

答えて

4

割り込みで「シャットダウン」できるようにコードを設計しようとしています。主に、これは、Javaの同時実行パッケージのExecutorフレームワークがinterruptを使用して実行中のタスクをキャンセルするためです。また、「シャットダウン」タスクは、殺されるタスクの内部を知る必要はありません。

しかし、それは割り込みを無視しますServerSocketコンストラクタで作成したサーバーcreated from a ServerSocketChannel.あるない限りacceptへの呼び出しが割り込みに応答しないだろう、と私はこれを再構成する方法を発見していません。

サーバーを作成するコードを変更できない場合は、closeをサーバーソケットに呼び出す別のスレッドを用意します。これにより、サーバーソケットの作成方法に関係なく、acceptでブロックされたスレッドの例外が発生します。

これはSSLを使用すると非常に苦しいことになります。 JSSEソケットはInterruptibleChannelから作成されず、スレッドの単純な割り込みに応答しません。


クライアントに通知することなくサーバーを閉じることができないという質問に気付いただけです。ソケットを正常に中断すると、その処理が終了します。

acceptへの呼び出しでは、サーバソケットがacceptでブロックされているとクライアントが接続されないため、これは問題ではありません。これは、現在の接続を表すSocketインスタンスの問題にすぎません。

通知要件を満たしていない場合は、NIOのServerSocketChannelをノンブロッキングモードで使用するためのリワークが必要な場合があります。

+0

mmm良い答え..たぶん私は問題へのアプローチを変更します。クライアント側のサーバーシャ​​ットダウンをtry-catchで管理します。 –

0

Thread.interrupt()を試しましたか?

このスレッドが中断 チャネル時にI/O 操作でブロックされている場合、チャネルは 閉じられます、スレッドの割り込みステータス が設定され、スレッドが ClosedByInterruptExceptionを受け取ります。

このスレッドが セレクターでブロックされている場合は、スレッドの割り込み ステータスが設定され、それだけでセレクタの ウェイクアップかのように、おそらくゼロ以外 値は、選択 操作からすぐ を返します。メソッドが呼び出されました。

+0

私はthis.interrupt()を試しました。シャットダウン()の中では動作しません... –

+0

割り込みしたいスレッド(つまりブロックされたスレッド)で呼び出す必要があります –

2

別のスレッドからソケットを閉じることができるはずです。

2

キャンセル(キャンセルポイントに依存する割り込みポイントに依存します)と閉じる(キャンセルはファイルディスクリプタを閉じることには反応しません)。受け入れを続行しないように通知するには、acceptと通信する必要があります(sendtoをシャットダウン通知で試してください)。少なくともこれはLinuxの場合です。それが他のプラットフォーム上でどのようなものかわからない。

+0

この問題をどうやって解決しますか? 多くの人がクローズがうまくいくと言っていますが、私の場合はLinux上で動作しません。 – Djvu

1

私は同じ問題に直面しています。私の実際の解決策は、ServerSocketオブジェクト(serverSocket.close())を閉じることです。これを行うと、accept()メソッドはあなたがしたいことであるSocketExceptionをスローします。

Vincent

関連する問題