Search code examples
javasocketsobjectinputstreamobjectoutputstream

ObjectInputStream does not read all objects from the output stream


I'm trying to send objects from a server to a rendering client, through a socket. The first list of Entity-objects consists of 8 entities, but many more are added to the list. My server can end up writing hundreds of objects to an ObjectOutputStream, but the client only reads the initial 8.

I have tried calling the flush() both before and after the writeObject method, but this does not seem to make a difference. I have narrowed the problem down to be client-sided.

The server writes an ArrayList to the stream using this method:

private void sendEntities() {
    try {
        ArrayList<Entity> entities = engine.requestEntities();
        System.out.println("Entities sent: " + entities.size());
        objectOut.writeObject(entities);
        // objectOut.flush(); Does not fix the problem
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The client reads and returns the objects to a setter-method that draws the them on the screen, but this is the only area that tries to read objects from the stream.

private ArrayList<Entity> requestEntities() {
    try {
        out.writeUTF("REQ_ENT()");
        // The client only receives 8 entity-objects every time
        ArrayList<Entity> entitiesReceived = (ArrayList<Entity>) objectIn.readObject();
        in.readUTF();
        return entitiesReceived;

    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    return null;
}

I expected the list of objects read from the inputstream to match the amount of objects written to the outputstream, but the list read from the inputstream stays the same. It works as expected the first time requestEntities() are called, but not on subsequent calls.

EDIT: a link to the github repository has been added

EDIT 2: The ObjectOutputStream sends a reference to a previously sent object, as pointed out by Johannes Kuhn. I added a line of code that seems to have solved the issue. I make a copy of the entities list, and write this copy to the stream instead.

private void sendEntities() {
    try {
        ArrayList<Entity> entities = engine.requestEntities();
        ArrayList<Entity> copy = new ArrayList<>(entities);
        System.out.println("Entities sent: " + entities.size());
        objectOut.writeObject(copy);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Link to github repository


Solution

  • The problem is that ObjectStreams keep track of already sent objects, and instead of sending them again, they will just reference the previous object.

    Make a copy of your ArrayList and send the new ArrayList.

    tl;dr: Serialization was not intended for server/client comunication.