Java - 客户端在连接时出错

时间:2014-11-05 22:39:08

标签: java multithreading networking javafx

我正在开发一个简单的Java消息传递程序。在开始研究更复杂的功能之前,我想让基本系统正常工作。目前

  1. 多个客户端可以连接
  2. 多个客户端可以发送服务器接收的消息
  3. 服务器在客户端终止时关闭连接
  4. 这段代码特别是出现错误的原因。它是我的ClientThread.java线程中的run()方法(实现了runnable)。该线程用于处理来自服务器的传入消息(发送消息可以正常工作)。

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    
    import javafx.application.Platform;
    import javafx.scene.Scene;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    
    
    public class ClientThread implements Runnable{
        private Socket server;
        private DataInputStream in;
        private DataOutputStream out;
        public Text msgContent;
        public void login(Stage stage, Scene main, String username, String password, String portString, String host) {
        try {
            int port = Integer.parseInt(portString);
            this.server = new Socket(host, port);
    
            this.in = new DataInputStream(server.getInputStream());
            this.out = new DataOutputStream(server.getOutputStream());
            stage.setScene(main);
            Platform.runLater(new ClientThread());
        }
        catch (NumberFormatException e) {
            System.out.println("Invalid Port");
            return;
        }
        catch (IOException e) {
            System.out.println("Error Connecting to Server");
            return;
        }
    }
    public void run() {
        String msg = "";
    
        try {
    
            while (true) {
                msg = in.readUTF(); //This line gives Errors
                System.out.println("Read message from server");
                msgContent.setText(msgContent.getText() + msg + "\n");
                System.out.println("Added message from server to view");
            }
    
        }
        catch(Exception ioe) {
            ioe.printStackTrace();
            System.out.println("Failed to read message from server and add to view.");
        }
    
    }
    public void sendMsg(String msg) {
        try {
            out.writeUTF(msg);
        } catch (Exception ioe) {
            ioe.printStackTrace();
        }
    }
    }
    

    请注意,msgContent是我的JavaFX前端和服务器的inputStream中的Text对象。我的完整代码是here。我得到的错误是

      

    显示java.lang.NullPointerException       在ClientThread.run(ClientThread.java:42)       at com.sun.javafx.application.PlatformImpl $ 6 $ 1.run(Unknown Source)       at com.sun.javafx.application.PlatformImpl $ 6 $ 1.run(Unknown Source)       at java.security.AccessController.doPrivileged(Native Method)       at com.sun.javafx.application.PlatformImpl $ 6.run(Unknown Source)       at com.sun.glass.ui.InvokeLaterDispatcher $ Future.run(Unknown Source)       at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)       at com.sun.glass.ui.win.WinApplication.access $ 300(未知来源)       at com.sun.glass.ui.win.WinApplication $ 4 $ 1.run(Unknown Source)       在java.lang.Thread.run(未知来源)   无法从服务器读取消息并添加到视图。

    另请注意,我使用Platform.runLater()来运行此方法。我想知道如何解决上述错误,以便我的代码可以工作。提前谢谢。

1 个答案:

答案 0 :(得分:1)

NullPointer异常的原因

in为空。

发生NullPointerException是因为在此调用中您创建了ClientManager类的新实例:Platform.runLater(new ClientThread());,因此它不会使用已初始化in和{{}的ClientManager的现有实例。 1}}成员。相反,您可以使用out来摆脱NullPointerException。

但是,您的代码还有其他问题......

不正确的并发编程

您正在挂起JavaFX应用程序线程,这将阻止您的应用程序呈现或响应UI输入。永远不要等待JavaFX应用程序线程。

完成您要做的事情的一种方法是使用JavaFX concurrency utilities,尤其是Task

在它自己的线程上运行任务,然后它可以循环,永远接受输入,它不会阻止你的UI线程。您可以(可能)使您的线程成为非守护程序线程,以便在所有其他守护程序线程完成时自动退出。您可以使用Platform.runLater将输入反馈回UI。但是,对于您想要更新某些消息文本的简单示例,您可以调用updateMessage(请注意,这不需要Platform.runLater调用,因为Task类会为您处理这类详细信息)。要更新消息标签,可以将其text属性绑定到任务的消息属性。有关如何在Task javadoc中执行此操作的示例。

相关问题