NullpointerException при попытке подключения к локальному серверу - PullRequest
0 голосов
/ 26 апреля 2018

Название может быть не очень ясным, и я не уверен, как мне сформулировать свой вопрос, но вкратце я пытаюсь создать программу "чат" на Java. Я использую 2 разных файла ChatServer и ChatClient.

Как работает программа, вы сначала открываете ChatServer, а затем ChatClient для подключения к ChatServer. Для подключения вам необходимо сначала написать имя пользователя в первом текстовом поле и нажать клавишу ввода. Затем программа пытается подключить вас к серверу, и вот здесь начинается проблема.

Каждый раз, когда я пытаюсь подключиться к серверу, я получаю nullpointerexception, и я не могу понять, почему. Я долго пытался понять, но не вижу ошибки.

Смысл программы в том, что несколько ChatClients могут подключаться к ChatServer (максимум 5 человек) и писать друг другу. Я знаю, что вопрос очень конкретный, и я надеюсь, что если кто-нибудь может указать мне правильное направление, я был бы очень счастлив!

ChatServer

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()));
         }
    }
}

ChatClient

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)

1 Ответ

0 голосов
/ 26 апреля 2018

Свойство outputToUsers не инициализировано и поэтому равно null.
Это вызывает исключение в AddUserToChat.run() при вызове establishUserConnection для оператора outputToUsers.add(toUser).
Это исключение перехватывается, так что removeUser называется.
В этом методе оператор outputToUsers.remove(toUser) вызывает новое исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...