【问题标题】:NullpointerException when trying to connect to localhost server尝试连接到 localhost 服务器时出现 NullpointerException
【发布时间】:2018-10-07 00:04:32
【问题描述】:

标题可能不是很清楚,我不知道应该如何表达我的问题,但总之我正在尝试用java创建一个“聊天”程序。我使用 2 个不同的文件 ChatServer 和 ChatClient。

程序的工作原理是您首先打开 ChatServer,然后打开 ChatClient 以连接到 ChatServer。要连接,您首先需要在第一个 TextField 中输入用户名,然后按 Enter。然后程序尝试将您连接到服务器,这就是问题开始的地方。

每次我尝试连接到服务器时,我都会收到 nullpointerexception,我不明白为什么。我尝试了很长时间才能理解,但我无法看到错误。

程序的重点是多个 ChatClients 可以连接到 ChatServer(最多 5 人)并相互写入。我知道这个问题非常具体,我希望如果有人能指出我正确的方向,我会非常高兴!

聊天服务器

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;

public class ChatServer extends Application 
{
    private ArrayList<ObjectOutputStream> outputToUsers;
    private TextArea taServer = new TextArea();
    private static final int MAX_USERS = 5;
    private boolean acceptingNewUsers = true;
    private int connectedUsers = 0;
    private static final int port = 4999;

    public static void main(String[] args) 
    {
        launch(args);
    }

    @Override  
    public void start(Stage primaryStage) 
    { 
        initializePrmaryStage(primaryStage);

        new Thread( () -> 
        { 
          try 
          { 
            // Create a server socket 
            @SuppressWarnings("resource")
            ServerSocket serverSocket = new ServerSocket(port);
            Platform.runLater(() -> taServer.appendText(new Date() + ": Server started at socket: " + port + '\n'));  
            acceptUsers();

            while (true) 
            { 
                if (acceptingNewUsers)
                {
                     // Listen for a new connection request 
                    Socket socket = serverSocket.accept();

                    connectedUsers++;
                    if (connectedUsers == MAX_USERS)
                        refuseNewUsers();

                  // Create and start a new thread for the connection 
                  new Thread(new AddUserToChat(socket)).start(); 
                }
            } 
          } 
          catch(IOException ex) 
          { 
            System.err.println(ex); 
          } 
        }).start(); 
     } 

    private void initializePrmaryStage(Stage stage)
    {
        taServer.setMinHeight(450);

         // Create a scene and place it in the stage 
        Scene scene = new Scene(new ScrollPane(taServer), 450, 400); 
        stage.setTitle("ChatServer"); // Set the stage title 
        stage.setScene(scene); // Place the scene in the stage 
        stage.show(); // Display the stage 
    }

    private void acceptUsers()
    {
        acceptingNewUsers = true;
        Platform.runLater(() -> taServer.appendText(new Date() + ": " + "Accepting users" + '\n'));

    }

    private void refuseNewUsers()
    {
        acceptingNewUsers = false;
        Platform.runLater(() -> taServer.appendText("Maximum user capacity reached." + '\n'));
    }

    private void writeToAll(String s)
    {
        try 
        {
            for (int x = 0; x < outputToUsers.size(); x++)
            {
                outputToUsers.get(x).writeObject(s);
                outputToUsers.get(x).flush();
            }
        } catch (IOException ex) 
        {
            ex.printStackTrace();
        } 
    }

    private void writeToLog(String s)
    {
        Platform.runLater(() -> 
        { 
            taServer.appendText(s); 
        }); 
    }

    private class AddUserToChat implements Runnable 
    {
         private ObjectInputStream fromUser;
         private ObjectOutputStream toUser;
         private String username;
         private Socket userSocket;

        @SuppressWarnings("unused")
        public AddUserToChat(Socket userSocket) 
         {
             this.userSocket = userSocket;
             connectedUsers++;
         }

        @Override
        public void run() 
        {
             try 
             {
                establishUserConnection();
                readMessagesFromUser();
             } 
             catch (Exception e) 
             {
                 System.err.println(e.getMessage());
                 removeUser();
             }
        }
         /*
         * Connects user to server
         * @throws IOException if {@link ObjectInputStream#readUTF()} encounters an error
         */
         private void establishUserConnection() throws IOException 
         {
             // Get input and output streams from socket
             toUser = new ObjectOutputStream(userSocket.getOutputStream());
             fromUser = new ObjectInputStream(userSocket.getInputStream());

             // Read and save username and save OOS to user in outputToUsers in ChatServer class
             username = fromUser.readUTF();
             outputToUsers.add(toUser);

             writeToLog(username + " joined the chat.");
             writeToAll(username + " joined the chat.");
         }

         /**
         * Removes user from server
         */
         private void removeUser() 
         {
             // Decrease user counter and remove OOS to user
            connectedUsers--;
            outputToUsers.remove(toUser);

             writeToLog(username + " left the chat.");
             writeToAll(username + " left the chat.");

             // If server doesn't accept new users, start accepting them once again
             if (!acceptingNewUsers) acceptUsers();
         }

         /**
         * Continually read messages from user
         *
         * @throws IOException if {@link ObjectInputStream#readUTF()} encounters an error
         */
         private void readMessagesFromUser() throws IOException 
         {
             while (true)
                 writeToAll(String.format("%s wrote: %s", username, fromUser.readUTF()));
         }
    }
}

聊天客户端

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class ChatClient extends Application
{
      private ObjectOutputStream toServer = null; 
      private ObjectInputStream fromServer = null;

      private GridPane gridpane = new GridPane();
      private BorderPane mainPane = new BorderPane();

      private TextField tfUsername = new TextField(); 
      private TextField tfUserInput = new TextField(); 
      private TextArea ta = new TextArea();
      private String username = "";
      private String userinput = "";
      private Socket socket;


    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception 
    {
        // Panel p to hold the label and text field 
        BorderPane paneForTextField = new BorderPane(); 
        paneForTextField.setPadding(new Insets(5, 5, 5, 5));  
        paneForTextField.setStyle("-fx-border-color: green"); 

        gridpane.add(tfUsername, 0, 0);
        gridpane.add(tfUserInput, 0, 1);

        initializeUsernameTextField();
        initializeUserInputTextField();

        tfUserInput.setPrefWidth(400.0);

        gridpane.setPrefWidth(450.0);
        gridpane.setVgap(5.0);
        gridpane.setHgap(25.0);
        gridpane.setAlignment(Pos.CENTER);
        paneForTextField.setBottom(gridpane);

        ta.setPrefHeight(450);
        mainPane.setCenter(new ScrollPane(ta)); 
        mainPane.setBottom(paneForTextField); 

        initializePrimaryStage(primaryStage);

        tfUsername.setOnAction(e -> 
        { 
            if (!tfUsername.getText().equals(""))
            {
                username = tfUsername.getText().trim();
                connecToServer();
            }
        }); 

        if (!username.equals(""))
        {
            tfUserInput.setOnAction(e -> 
            { 
              // Get user input
            String UserInput = tfUserInput.getText();

            // Send string
            sendToServer(UserInput);

            // Get string
            receiveDataFromServer();

            writeToLog(userinput); 
            }); 
        }
    }
    private void initializeUsernameTextField()
    {
        tfUsername.setPrefWidth(400.0);
        tfUsername.promptTextProperty().set("Enter username here...");
    }

    private void initializeUserInputTextField()
    {
        tfUserInput.setPrefWidth(400.0);
        tfUserInput.promptTextProperty().set("Enter message here...");
    }

    private void initializePrimaryStage(Stage stage)
    {
        // Create a scene and place it in the stage 
        Scene scene = new Scene(mainPane, 450, 400); 
        stage.setTitle("Chat Client"); // Set the stage title 
        stage.setScene(scene); // Place the scene in the stage 
        stage.show(); // Display the stage 
    }

    private BorderPane getBorderPane() {return mainPane;}

    private void connecToServer()
    {
        establishServerConnection();
    }

    private void establishServerConnection()
    {
        try 
        { 
          socket = new Socket("localhost", 4999);  
          fromServer = new ObjectInputStream(socket.getInputStream()); 
          toServer = new ObjectOutputStream(socket.getOutputStream());
          sendToServer(username);
        } 
        catch (IOException ex) 
        { 
          ta.appendText(ex.toString() + '\n'); 
        } 
    }

    private void receiveDataFromServer()
    {
        try 
        {
            userinput = fromServer.readUTF();
        } catch (IOException ex) 
        {
            System.err.println(ex); 
        }
    }

    private void sendToServer(String s)
    {
        try 
        {
            toServer.writeObject(s);
            toServer.flush();
        } 
        catch (IOException ex) 
        {
            System.err.println(ex); 
        }

    }

    private void writeToLog(String s)
    {
        ta.appendText(tfUsername + "wrote: " + s + "\n"); 
    }
}

TLDR;

尝试连接服务器时出现nullpointerexception,我无法找到问题所在。

错误消息:

Exception in thread "Thread-5" java.lang.NullPointerException
    at chapter19.ChatServer$AddUserToChat.removeUser(ChatServer.java:171)
    at chapter19.ChatServer$AddUserToChat.run(ChatServer.java:143)
    at java.lang.Thread.run(Unknown Source)

【问题讨论】:

  • 你没有初始化removeUser所以你访问它时它是空的
  • 异常很明显。 removeUser() 方法有问题。为什么不直接调试您的代码?
  • 一目了然,establishUserConnection();readMessagesFromUser(); 中的任何一个都失败了,因此输入您的 try...catch 正在尝试删除未连接的用户。

标签: java server nullpointerexception localhost


【解决方案1】:

属性outputToUsers 未初始化,因此等于null
这会导致在为语句 outputToUsers.add(toUser) 调用 establishUserConnection 时在 AddUserToChat.run() 内引发异常。
这个异常被捕获,所以removeUser被调用。
在这个方法中,outputToUsers.remove(toUser) 语句会导致一个新的异常。

【讨论】:

  • 你说的太对了,我的朋友!我什至没有考虑。将 ArrayList 初始化更改为: private static ArrayList outputToUsers = new ArrayList();现在我没有抛出异常,但是每次我尝试连接时用户都会断开连接。我需要检查一下,看看哪里出了问题,但这很有帮助!谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-07-03
  • 2020-10-04
  • 2023-04-02
  • 1970-01-01
  • 2014-08-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多