我正在研究Javafx。我创建了一个echo ServerClient系统,即将数据发送到服务器并返回给所有客户端(广播)。当客户端向服务器发送数据时,它工作正常。但是当服务器将数据发送回客户端时,框架会冻结。这是代码: 客户端:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.rajeshpatkar;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* @author Dimpi
*/
public class Client extends Application{
int flag = 999;
public void start(Stage primaryStage) throws Exception {
Connect cnn = new Connect(primaryStage);
cnn.sconnect();
}
public static TextArea Frame(Stage primaryStage, PrintWriter nos, BufferedReader nis) throws IOException {
TextField tf = new TextField();
TextArea ta = new TextArea();
Button btn = new Button();
btn.setText("Click");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String get = tf.getText();
nos.println(get);
try {
Connect.chat(nis,ta);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
BorderPane root = new BorderPane();
root.setCenter(ta);
BorderPane panel = new BorderPane();
root.setBottom(panel);
panel.setCenter(tf);
panel.setRight(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
return ta;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
class Connect {
Stage primaryStage;
Connect(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public void sconnect() throws IOException {
System.out.println("Client Signing IN");
Socket soc = new Socket("localhost", 9081);
PrintWriter nos = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(soc.getOutputStream()
)
), true);
BufferedReader nis = new BufferedReader(
new InputStreamReader(soc.getInputStream()
)
);
TextArea ta=Client.Frame(primaryStage, nos, nis);
}
public static void chat(BufferedReader nis,TextArea ta) throws IOException{
String set = nis.readLine();
while (!set.equals("End")) {
ta.appendText(set+"\n");
set = nis.readLine();
}
}
}
Server: /*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.rajeshpatkar;
import static com.rajeshpatkar.Server.a1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* @author Dimpi
*/
public class Server extends Application {
public static ArrayList<PrintWriter> a1=new ArrayList<PrintWriter>();
@Override
public void start(Stage primaryStage) throws IOException {
System.out.println("Server signing IN");
ServerSocket ss = new ServerSocket(9081);
for (int i = 0; i < 5; i++) {
Socket soc = ss.accept();
Conversation c = new Conversation(soc);
c.start();
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
class Conversation extends Thread {
Socket soc;
Conversation(Socket soc) {
this.soc = soc;
}
public void run() {
try {
PrintWriter nos = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(soc.getOutputStream()
)
), true);
BufferedReader nis = new BufferedReader(
new InputStreamReader(soc.getInputStream()
)
);
Server.a1.add(nos);
String get=nis.readLine();
while(true){
for(PrintWriter p:a1){
System.out.println(get);
p.println(get);
}
get=nis.readLine();
}
} catch (Exception e) {
}
}
}
答案 0 :(得分:0)
冻结客户端ui的问题导致您的方法:chat()
。这是你的按钮调用的。它包含readLine()
的{{1}}方法,它将等待输入发生。此等待将导致冻结,因为它发生在应用程序线程上。
所以你可以做的是:在你的button-eventhandler上: only 写输出:
BufferedReader
但添加一个Thread,如果您的InputStream接收到输入,将更新TextArea,例如像这样:
String get = tf.getText();
nos.println(get);
并调用该方法一次:
static void handleInput(BufferedReader nis, TextArea ta) throws IOException {
final Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
String output;
while ((output = nis.readLine()) != null) {
final String value = output;
Platform.runLater(new Runnable() {
@Override
public void run() {
ta.appendText(value + System.getProperty("line.separator"));
}
});
}
return null;
}
};
new Thread(task).start();
}