0

I want to send two different objects on the same socket to my client application from my server application. From what I've read I am doing this the right way, but still I cannot send my second object to my client.

Here is my server code:

public class ServerThread implements Runnable {

String name = null;
Socket socket = null;

public ServerThread(Socket s, String name) {
    this.name = name;
    this.socket = s;
}

@Override
public void run() {

    try {
        ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
        RequestType request = (RequestType) serverInputStream.readObject();
        switch (request) {
            case LOGIN:
                serverInputStream = new ObjectInputStream(socket.getInputStream());
                RequestManager.manageLogin(serverOutputStream, serverInputStream);
                serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
                RequestManager.managePopulateTable(serverOutputStream);
        }
        serverOutputStream.close();
        serverInputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

And this is my server request manager

public class RequestManager {

public static void manageLogin(ObjectOutputStream serverOutputStream, ObjectInputStream serverInputStream) {
    ArrayList<ProductEntity> availableProducts = new ArrayList<>();
    try {
        UserEntity loggedUser = (UserEntity) serverInputStream.readObject();
        if (DatabaseManager.userConnect(loggedUser.getUsername(), loggedUser.getPassword())) {
            serverOutputStream.writeObject(loggedUser);
        }
        else
            serverOutputStream.writeObject(null);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void managePopulateTable(ObjectOutputStream serverOutputStream) {
    ArrayList<ProductEntity> availableProducts = DatabaseManager.getProducts();
    try {
        serverOutputStream.writeObject(availableProducts);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

The problem occurs when I try to send "availableProducts" to client.

Octavian Marian
  • 65
  • 3
  • 11
  • 1
    Stop creating and closing new object streams, and use the same ones for the life of the socket, at both ends. – user207421 May 24 '17 at 17:39

1 Answers1

0

You've a lot of problems with the following code:

ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
...
switch (request) {
    case LOGIN:
        serverInputStream = new ObjectInputStream(socket.getInputStream());
        ...
        serverOutputStream = new ObjectOutputStream(socket.getOutputStream());

When you open an ObjectOutputStream, header information is written to the stream to help manage the object serialization. Similarly, when you open an ObjectInputStream, the header information is read from the stream.

But here, you are opening a second ObjectInputStream (which will read header information from the same socket stream) and a second ObjectOutputStream (which will write header information to the same socket stream). As a result, the object streams on the sockets will be in a bad state - object(s) should follow the header information, not another Object Stream header.

Do not open your object stream multiple times.

AJNeufeld
  • 8,526
  • 1
  • 25
  • 44
  • For my serverInputStream, if I do not open a second ObjectInputStream it throws "java.io.StreamCorruptedException: invalid type code: AC". And for serverOutputStream, even if I do not open a second ObjectOutputStream, I get the same error – Octavian Marian May 24 '17 at 17:15
  • Sounds like your client code might be doing something similar, and opening a second `ObjectOutputStream` on the same socket output stream. Only wrap a socket stream (any stream, actually) once. – AJNeufeld May 24 '17 at 17:23