2017-01-04 4 views
4

JavaFXでクライアント/サーバーチャットアプリケーションを作成しました。私のServerControllerは、別のスレッドで実行されている「Start Server」ボタンが押されたときにServer Objectを作成します。私はデフォルト「でウィンドウを閉じるたびJavaFX - アプリケーションを終了する前に、実行中のすべてのスレッドを閉じるにはどうすればいいですか?

がX'-ボタンServerのスレッドが終了するが、サーバーが終了したことをアクティブなクライアントに通知しません:

は、ここに私の問題です。私は私の 'Stop-Server'-Buttonのようにサーバーがシャットダウンしていることをクライアントに知らせる必要があります。私のサーバはコントローラオブジェクトへの参照を保持します。

public class ServerController { 

@FXML 
TextArea chatEvent_txt; 
@FXML 
Button start_btn; 
@FXML 
Button stop_btn; 
private Server server; 
private boolean started = false; 
private StringBuffer chatEvents = new StringBuffer(""); 

/** 
* @param e 
*/ 
@FXML 
public void startButtonAction(ActionEvent e) { 
    if (!started) { 
     this.server = new Server(this); 
     new Thread(server).start(); 
     started = true; 
     chatEvents = chatEvents.append("Server started.." + "\n"); 
     chatEvent_txt.setText(chatEvents.toString()); 
    } else { 
     chatEvent_txt.setText("Server already started\n"); 
    } 
} 

はここでサーバーがシャットダウンされることを、すべてのクライアントに通知し、そのようなすべてのソケットとスタッフを閉じ、私の「ストップServer'-ボタンです。

@FXML 
public void stopButtonAction(ActionEvent e) { 
    if (started) { 
     server.setRunning(false); 
     chatEvent_txt.setText("Server wurde gestoppt\n"); 
     started = false; 
    } 
} 

メソッドsetRunning();新しいクライアントを受け入れるwhileループからスレッドが離れるように変数をfalseに設定するだけです。 whileループが残っていると、サーバーはすべてのクライアントにメッセージを送信し、サーバーがシャットダウンされることを知ります。私のサーバー上の

実行方法:

@Override 
public void run() { 
    try { 
     serverSocket.setSoTimeout(500); 
     while (running) { 
      try { 
       clientSocket = serverSocket.accept(); 
       new Thread(new Listener(clientSocket, this)).start(); 
      } catch (IOException e) { 
      } 
     } 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 

    try { 
     broadcastMessage(new Message(Message.Type.DISCONNECT_OK, "Server")); 
     serverSocket.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

がどのように私は私の 『停止サーバー』 -Buttonと同じことを行うには「X 'ボタンを伝えることができますか?

+2

[onCloseRequest](https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Window.html#onCloseRequestProperty)ハンドラを実装し、このハンドラのサーバーを正常にシャットダウンする必要があります。 –

+0

与えられた答えが働いている間、私は[shutdown-hook](http://stackoverflow.com/questions/2921945/useful-example-of-a-shutdown-hook-in-java)を好むでしょう。プログラムがCtrl + Cで停止している場合に呼び出されます。 – MalaKa

+1

@MalaKa FX Toolkitと対話するシャットダウンフックを得るのはかなり難しいです(または正しい実装が何であるかを知ることさえあります)。実際、[documentation](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-)には、「他のスレッドを使用しようとする試みは、たとえば、AWTのイベントディスパッチスレッドなどのベースのサービスは、デッドロックにつながる可能性があります。 –

答えて

2

@FXML 
public void stopButtonAction(ActionEvent e) { 
    shutdown(); 
} 

public void shutdown() { 
    if (started) { 
     server.setRunning(false); 
     chatEvent_txt.setText("Server wurde gestoppt\n"); 
     started = false; 
    } 
} 

としてそれをリファクタリングし、FXMLをロードし、表示するときに、あなたが行うことができます:

FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml")); 
Parent root = loader.load(); 
Scene scene = new Scene(root); 
someStage.setScene(scene); 

ServerController controller = loader.getController(); 
someStage.setOnCloseRequest(e -> controller.shutdown()); 

あなたは閉じるボタンが押されたときに閉じないようにウィンドウが必要な場合(たとえば、ウィンドウをプログラムで閉じる前にすべてを正常に終了するまで待つ必要がある場合)、ハンドラでe.consume()を呼び出すことができます。

+0

ありがとう、これは働いた。私はアプリケーションクラスからstop()メソッドを上書きして解決しました。私はそれが正しい方法であるかどうか分からない。 – jslr

関連する問題