2017-01-04 6 views
4

JavaFX로 클라이언트/서버 채팅 응용 프로그램을 만들었습니다. 내 ServerController는 별도의 스레드에서 실행중인 '서버 시작'버튼을 누르면 서버 객체를 만듭니다. 난 그냥 기본 '으로 창을 닫습니다 때마다JavaFX - 응용 프로그램을 종료하기 전에 실행중인 모든 스레드를 닫는 방법?

이는 x'--버튼 서버 스레드가 종료하지만 서버가 종료하는 활성 클라이언트를 통보하지 않습니다

여기 내 문제입니다. 내 'Stop-Server'버튼을 사용하는 것처럼 서버가 종료되었음을 클라이언트에게 알려야합니다. 내 서버에는 Controller 개체에 대한 참조가 있습니다.

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(); 
    } 

} 

가 어떻게 내 "서버 중지"- 버튼과 같은 작업을 수행 할 '는 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과 상호 작용하는 셧다운 훅 (hook)을 얻는 것은 꽤 어렵습니다 (또는 올바른 구현이 무엇인지 알기까지). 실제로 [documentation] (http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-)에는 "다른 스레드 기반 응용 프로그램을 사용하려고 시도합니다. 예를 들어, AWT 이벤트 발송 스레드와 같은 서비스 기반 서비스는 교착 상태가 발생할 수 있습니다. " –

답변

2

리팩토링 그것은 당신이로드하고 FXML을 표시 할 때 다음

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

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

로, 당신은 할 수 있습니다 :

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