1

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)
1
  • 1
    readObject() doesn't return null unless you wrote one at the peer. It isn't correct therefore to loop until it does so. You should be looping until you catch an EOFException. Commented Jul 9, 2013 at 0:07

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Ty for the reply, but i think this is not the problem, the write is executed in main thread. I created new thread to run the write code block but the same behaviour..
The problem is that you are writing from multiple threads - creating yet another write thread only makes it worse! You must treat _client as private property of the write thread, and not touch it from outside that thread.
Ok i understood, normally i write from the thread of the read() method of the client like this: Thread readThread = new Thread(new Runnable() { @Override public void run() { Object fromServer; try { while ((fromServer = _ois.readObject()) != null) { Protocol.processInput(fromServer, _state); }} }); readThread.start(); how would i access this thread to write?
I would make that Runnable into a class with a LinkedBlockingQueue of file lists. The button would just add to that queue, and the client thread would poll the queue once it finished sending its current set of files.
That was correct, read and write have to be in their own threads, thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.