ddarellis
ddarellis

Reputation: 3960

java.io.StreamCorruptedException with serialized objects

The problem is that i get java.io.StreamCorruptedException: invalid type code: 9E the code every time is different.

What i have is a client-server application and the problem occurs when the client is in upload state and server is in download state.

The user presses a button from the ui and all selected files are tranfered to server one by one.

This is the button code:

try {
    _client.setProtocolFiles(_uploadTree.getFiles());
if(_uploadTree.getFiles().getFiles().size() > 0) {
    _client.write("iwanttoupload");
} else {
    CustomDialog.showInfoDialog("Πρέπει να επιλέξετε αρχεία", "Προσοχή");
}
} catch (Exception e) {
    e.printStackTrace();
}

This is the client's upload state:

@Override
public void interact(Object theInput) throws Exception {
    if(theInput.equals("uploadedsuccessfully")) {
        System.out.println("uploadedsuccessfully");
        _client.setState(new TranferState(_client));
    } else if(theInput.equals("letsgo") || theInput.equals("sendmemore")) {
        if(_fileToBeSent < _client.getProtocolFiles().getFiles().size())
            sendFiles(theInput);
        else
            _client.write("iuploadedall");
        _fileToBeSent++;
    } else if(theInput.equals("idontunderstandyou")) {
        _client.setState(new TranferState(_client));
    }
}

private void sendFiles(Object theInput) throws Exception {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(new File(_client.getProtocolFiles().getFiles().get(_fileToBeSent).getPath()));
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        _client.getProtocolFiles().getFiles().get(_fileToBeSent).setFile(buffer);
        try {
            _client.write(_client.getProtocolFiles().getFiles().get(_fileToBeSent));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch(IOException ex) {
        System.out.println(ex.getMessage());
        _fileToBeSent++;
        interact(theInput);
    }
}

This is the server's download state:

@Override
public String reply(Object theInput) {
    String outPut = "";
    if(theInput.equals("iuploadedall")) {
        outPut = "uploadedsuccessfully";
        _connection.setConnectionState(new TranferState(_connection));
    } else if (theInput.equals("startedupload")) {
        outPut = "letsgo";
    } else if(theInput instanceof ProtocolFile) {
        try {
            System.out.println(theInput.toString());
            ProtocolFile file = (ProtocolFile)theInput;
            FileOutputStream fos = new FileOutputStream("C:\\" + file.getName());
            fos.write(file.getFile());
            fos.close();
            outPut = "sendmemore";

        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        outPut="idontunderstandyou";
        _connection.setConnectionState(new TranferState(_connection));
    }
    return outPut;

}

This all works great with this order:

  1. User clicks and sends "iwanttoupload"
  2. Server sends ok. ---- client and server are in the above states now.
  3. clients sends "startedupload"
  4. server sends "letsgo"
  5. client send ProtocolFile (Serialized)
  6. server sends "sendmemore" until he gets from client "iuploadedall"

This works great if user presses one time the button and wait for the upload to wait and then presses it again. If user press it before the upload is complete i get this exception.

One quick fix is to check when the user presses the button if client state is tranfer state, else not to perform the action, but i want to fix the problem with the socket or to understand why is this happening. I think that when it is trying to read the serialized object the new upload sends data and there is the mess. My implemented states will avoid the communication according to the messages but the messages are send and there is the problem.

Client write code:

public void write(Object credentials) throws Exception {
if (credentials != null && _socket !=null && !_socket.isClosed()) {
        _oos.writeObject(credentials);
} else {
     connect();
     _oos.writeObject(_credentials);
    _oos.flush();
    _oos.writeObject(credentials);
}
_oos.flush();
}

Server read code:

while ((input = ois.readObject()) != null) {
    if (_connectionState.getClass().equals(ClosedState.class)) {
    break;
}
oos.writeObject(Protocol.processInput(input, _connectionState));
oos.flush();
}

The exception comes here:

while ((input = ois.readObject()) != null)

Upvotes: 1

Views: 157

Answers (1)

Russell Zahniser
Russell Zahniser

Reputation: 16364

I suspect the problem is that in your button code you do an immediate write to the client:

if(_uploadTree.getFiles().getFiles().size() > 0) {
    _client.write("iwanttoupload");
}

If you are following the typical pattern of handling the client communication in a background thread, then you must only write to the stream from that thread. The button ought to just enqueue a notification that will be handled by that thread when it gets a chance.

You are seeing this error because "iwanttoupload" is inserted in the middle of an object being written by the background thread, thus corrupting the stream.

Upvotes: 1

Related Questions