<java>编译时,客户端/服务器聊天应用程序没有响应

时间:2018-02-10 07:36:28

标签: java sockets javafx crash serversocket

我正在尝试使用JavaFX在客户端和服务器之间创建双向聊天程序。每当我运行程序,Assignment5Server.java和Assignment5Client.java时,窗口就会冻结并说“#34;没有响应&#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);
}
}

1 个答案:

答案 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并且它将保持响应。