hakan eryargi a écrit :
hi,
It's not a problem on the server side. Your client *must* assume that
the received message may be received in pieces. Even the first int can
be received on 4 subsequent reads (not likely though).
You have to deal about fragmentation on both sides, btw. Read this :
http://mina.apache.org/handling-packet-fragementation.html
my server uses MINA with a custom codec and my client uses blocking IO.
codec is very similar to ObjectSerializationCodec except it uses a regular
ObjectOutputStream.
below is the encoder:
@Override
public void encode(IoSession session, Object message, ProtocolEncoderOutput
out) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
ObjectOutputStream oout = new ObjectOutputStream(bos);
oout.writeObject(message);
oout.flush();
byte[] bytes = bos.toByteArray();
IoBuffer buffer = IoBuffer.allocate(bytes.length + 4);
buffer.putInt(bytes.length);
buffer.put(bytes);
buffer.flip();
out.write(buffer);
}
on client, i create a DataInputStream over socket's input stream and use the
following code to read messages:
public Message read() throws IOException, ClassNotFoundException {
dataIn.readInt(); // skip the data size
ObjectInputStream oin = new ObjectInputStream(new
BufferedInputStream(dataIn));
return (Message) oin.readObject();
}
this throws no exceptions, seems to run fine except it skips some messages.
i suspected it was because of BufferedInputStream placed in the middle (it
may read more than required) so removed it but didnt help.
finally i tried to read *size* bytes into a byte array and create an
ObjectInputStream out of that and that solved the problem. the code is:
public Message read() throws IOException, ClassNotFoundException {
int size = dataIn.readInt(); // skip the data size
if (size <= 0)
throw new StreamCorruptedException("block size: " + size);
byte[] block = new byte[size];
int totalRead = 0;
while (totalRead < size) {
int read = dataIn.read(block, totalRead, size-totalRead);
if (read == -1)
throw new EOFException();
totalRead += read;
}
ObjectInputStream oin = new ObjectInputStream(new
ByteArrayInputStream(block));
return (Message) oin.readObject();
}
any ideas what's the problem in first approach ?
thanks,
r a f t