-1

I am working on a Java Client/Server that will communicate via String commands. The Server is near complete, but the Client freezes when creating the ObjectInputStream from the server. I have tried changing the I/O Streams on the server a few different ways, but no matter what I do I end up with the program freezing on the same line.

Server code:

public class Server {
  //a lot of other methods

  public void launchServer(){
  // Text area for displaying server console
    TextArea ta = new TextArea();

    // Create a scene and place it in the stage
    Stage console = new Stage();
    Scene scene = new Scene(new ScrollPane(ta), 450, 200);
    console.setTitle("Server"); // Set the stage title
    console.setScene(scene); // Place the scene in the stage
    console.show(); // Display the stage

    new Thread( () -> {
      ServerSocket serverSocket = null; Socket socket = null;
      ObjectInputStream fromClient = null; ObjectOutputStream toClient = null;

      Platform.runLater( () -> {
        ta.appendText("Server started at " + new Date() + '\n');
      });

      // Create a server socket
      try{
        serverSocket = new ServerSocket(8000); 

        while (true) {
          socket = serverSocket.accept();

          Platform.runLater( () -> {
            ta.appendText("Thread started at " + new Date() + '\n');
          });

          new MyThread(socket).start();
        }
      }
      catch(IOException e){e.printStackTrace();}
    }).start();
  }
}

MyThread:

class MyThread extends Thread{
  protected Socket socket;
  private String command;
  ObjectInputStream fromClient = null;
  ObjectOutputStream toClient = null;
  Homework6French schoolServer;
  Connection connection = schoolServer.connection;

  public MyThread(Socket clientSocket) {
    this.socket = clientSocket;
  }

  public void run() {
    try {
      // Create data input and output streams
      fromClient = new ObjectInputStream(socket.getInputStream());
      toClient = new ObjectOutputStream(socket.getOutputStream());

      while (true) {
        //read the command from the client
        command = (String) fromClient.readObject();

        //read the first word of the command, and cut it out of the command
        String comStart = command.substring(0, 3);
        command = command.substring(4);

        //run method based on what first word of command was
        switch(comStart){
          case "GGr":
            getGrade(); break;
          case "GSt":
            getStudents(); break;
          case "GCo":
            getCourses(); break;
          default:
            toClient.writeChars("Command not recognized"); break;
        }
      }
    }
    catch(IOException e){e.printStackTrace();}
    catch(ClassNotFoundException e){e.printStackTrace();}
    finally{
      try{
        fromClient.close();
        toClient.close();
      }
      catch(Exception e){e.printStackTrace();}
    }
  }
}

Client:

public class Client {
  //member data
  ObjectOutputStream toServer = null;
  ObjectInputStream fromServer = null;

  public void start(Stage primaryStage) {

    //...

    try {
      // Create a socket to connect to the server
      Socket socket = new Socket("localhost", 8000);
      System.out.println("socket made");

      // Create an input stream to receive data from the server
      fromServer = new ObjectInputStream(socket.getInputStream());
      System.out.println("fromSerrver made");
      // Create an output stream to send data to the server
      toServer = new ObjectOutputStream(socket.getOutputStream());
      System.out.println("toServer made");
    }
    catch (IOException ex) {
      ex.printStackTrace();
    }
  }
}

Server works fine on its own, Client launches okay and gets as far as printing "socket made", then gets stuck. Also of note is that before the try statement in the Client code, a JavaFX Stage is defined and created, and the window appears but the buttons never appear in the window.

I thought that perhaps I needed to have I/O Streams defined inside MyThread and before MyThread is called, but if I try to create an InputStream before the socket is accepted a NullPointerException is thrown. How can I understand why this InputStream freezes the client?

halfer
  • 19,824
  • 17
  • 99
  • 186

1 Answers1

2

You must create and flush the ObjectOutputStream first, before the ObjectInputStream, at at least one end. The safe way to ensure that is do it at both ends.

The reason is that the object output stream creates a stream header when constructed, and the object input stream reads it when constructed. So if both object input streams are constructed first, you deadlock.

if I try to create an InputStream before the socket is accepted a NullPointerException is thrown.

Of course it is. The Socket variable is still null. I don't know why you even tried it, or mention it here.

user207421
  • 305,947
  • 44
  • 307
  • 483