我正在尝试使用 JavaFX 创建客户端和服务器之间的双向聊天程序。每当我运行程序Assignment5Server.java和Assignment5Client.java时,窗口都会卡住并显示“没有响应”。此时我陷入了困境,当我设置流并尝试将文本附加到文本区域时,程序似乎遇到了问题。我觉得为了连接程序我可能会遗漏一些东西?我将发布迄今为止的代码。如果能帮助我找到解决方案,我将不胜感激!
这是作为服务器运行的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);
}
}
最佳答案
问题
您的 try catch block 正在阻塞 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 并且它将保持响应。
关于java - <Java> 客户端/服务器聊天应用程序在编译时没有响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48718402/