Reputation: 1065
I'm trying to transfer an object from a client (normal IO) to a server (NIO). Transmission works fine until the object reaches a certain size, then the server will throw a "StreamCorruptException" saying "invalid type code".
The method called on the server is the following:
private void read(SelectionKey key) throws IOException, ClassNotFoundException {
SocketChannel chan = (SocketChannel) key.channel();
//read message object
ByteBuffer buf = ByteBuffer.allocate(1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.capacity());
int length = 0;
int totalRead = 0;
int read = chan.read(buf);
System.out.println("read data " + read);
if (read >= 4) {
length = IoUtil.readInt(buf.array(), 0);
bos.write(buf.array());
buf.rewind();
totalRead += read;
LogUtil.log("length of data message is " + length);
}
while (totalRead < length) { //read until we get no more data
read = chan.read(buf);
if (read == -1) break;
if (read == 0) continue;
totalRead += read;
System.out.println("I've read " + read + " bytes. Total amount of bytes " + totalRead);
bos.write(buf.array());
buf.rewind();
}
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray(), 4, length);
ObjectInputStream inFromClient = new ObjectInputStream(bis);
Message msg = (Message) inFromClient.readObject();
SocketAddress sa = chan.socket().getRemoteSocketAddress();
LogUtil.log(msg.getIdentifier() + "-Message von " + sa);
commData.handleMessage(sa, msg);
}
I prepend the size of the object to make NIO play nicely. What am I missing here?
Upvotes: 1
Views: 184
Reputation: 533500
You have to consider that a message can be fragmented (which is what I suspect is happening here) or coalessed. This means you cannot assume that the start of a message and end of a message will be at the start or end of a read. (It typically is for small messages with a significant break between them, but this fails randomly)
The safe approach is to send a length at the start and read until you have that length. If you have more, keep the extra for the next read.
Upvotes: 2