我正在尝试使用JavaFX在客户端和服务器之间创建双向聊天程序。每当我运行程序,Assignment5Server.java和Assignment5Client.java时,窗口就会冻结并说“#34;没有响应"”。此时我仍然坚持要做什么,当我设置我的流并尝试将文本附加到textArea时,程序似乎遇到了问题。我觉得我可能会遗漏一些东西以便连接程序?我将发布到目前为止的代码。我非常感谢帮助我找到解决方案的任何帮助或见解!
这是作为服务器运行的Assignment5Server.java程序
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
public class Assignment5Server extends Application {
TextArea messages = new TextArea();
String inputMessage;
String outputMessage;
ObjectOutputStream output;
ObjectInputStream input;
Socket clientSocket;
public void printToTextArea(String text) {
messages.appendText(text);
}
public void serverChat(String text) {
try {
output.writeObject("Server: "+ text + "\n");
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
messages.appendText("Server: "+text+ "\n");
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("ChatServer");
messages.setEditable(false);
messages.setPrefHeight(550);
Label serverLabel = new Label("Server");
Label clientLabel = new Label("Connected to: Client");
TextField textField = new TextField();
textField.setOnAction(e->{
outputMessage = textField.getText();
serverChat(outputMessage);
textField.setText("");
});
VBox root = new VBox( 5 ,clientLabel, messages,serverLabel, textField);
root.setPrefSize(600, 600);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(80);
printToTextArea("Waiting to connect to client...\n");
clientSocket = serverSocket.accept();
printToTextArea("Connected to client!");
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.flush();
input = new ObjectInputStream(clientSocket.getInputStream());
/* while(input.readObject()!= null)
{
inputMessage = (String) input.readObject();
printToTextArea(inputMessage);
}
*/
serverSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main( String[] args) {
launch(args);
}
}
和Assignment5Client。 java文件
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.*;
@SuppressWarnings("unused")
public class Assignment5Client extends Application {
TextArea messages = new TextArea();
String outputMessage;
String inputMessage;
ObjectOutputStream output;
ObjectInputStream input;
public void printToTextArea(String text) {
messages.appendText(text);
}
public void clientChat(String text) {
try {
output.writeObject("Client: "+ text + "\n");
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
messages.appendText("Client: "+text + "\n");
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("ChatClient");
messages.setEditable(false);
messages.setPrefHeight(550);
Label serverLabel = new Label("Connected to: Server");
Label clientLabel = new Label("Client");
TextField textField = new TextField();
textField.setOnAction(e->{
outputMessage = textField.getText();
clientChat(outputMessage);
textField.setText("");
});
VBox root = new VBox( 5 ,serverLabel, messages,clientLabel, textField);
root.setPrefSize(600, 600);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
try {
Socket socket = new Socket("127.0.0.1",80);
output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
input = new ObjectInputStream(socket.getInputStream());
printToTextArea("Streams Connected!\n");
/*try {
while(input.readObject()!= null) {
inputMessage = (String) input.readObject();
printToTextArea(inputMessage);
}
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
*/
socket.close();
}
catch (UnknownHostException e) {
System.out.println("Unknown host exception");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("IO exception");
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 0 :(得分:0)
问题
您的try catch块阻止了JavaFX线程。 JavaFX使用主线程来更新GUI并使其保持响应。您当前正在等待来自服务器的响应来阻止此线程。
try {
Socket socket = new Socket("127.0.0.1",80);
output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
input = new ObjectInputStream(socket.getInputStream());
printToTextArea("Streams Connected!\n");
/*try {
while(input.readObject()!= null) {
inputMessage = (String) input.readObject();
printToTextArea(inputMessage);
}
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
*/
socket.close();
}
catch (UnknownHostException e) {
System.out.println("Unknown host exception");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("IO exception");
}
有两种方法可以解决此问题。
我建议在另一个帖子中运行它。
我有一个例子,客户端代码在一个单独的类中。 在主类中,我创建了一个ExecutorService,它有一个4个线程的线程池。 这里发生了什么?我创建了一个服务器和3个客户端来测试服务器/客户端通信。
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.execute(Server::new);
Thread.sleep(1000);
executorService.execute(() -> new Client("Ruby"));
Thread.sleep(1000);
executorService.execute(() -> new Client("Simon"));
Thread.sleep(1000);
executorService.execute(() -> new Client("Peter"));
executorService.awaitTermination(60, TimeUnit.SECONDS);
}
现在您可以指定自己的客户端类并在其中实现您的代码。你阻塞该线程并不重要,因为JavaFX线程仍然可以更新GUI并且它将保持响应。