help -- extra byte in inputStream

I have a large distributed application which communicates to remote nodes by transmitting byte arrays (serialized objects). I lay out the lengh of each array as a four byte integer -- followed by the byte array itself.

Each writer and reader is run under a separate thread on each side (four threads per socket). All IO is blocking.

My problem is that several times a day random nodes seem to read an extra byte -- which displaces everything and forces me to reset the sockets and recover. The phenomenum is load related, but not dependant. My code is dirt-simple:

public static byte[] readall(InputStream i , int cnt) throws java.io.IOException {

byte[] b = new byte[cnt];

int offset = 0;

int residual = cnt;

int chunk = 0;

while (offset < cnt - 1) {

try {

chunk = i.read(b, offset, residual);

} catch (java.lang.IndexOutOfBoundsException e) {

System.out.println("Out of bounds, chunk = " + chunk + ", offset = " + offset + ", resid = " + residual);

}

if (chunk == residual)

break;// we're done

if (chunk >= 0 ) {

offset += chunk;// move the chains

residual -= chunk; // countdown

} else

throw new java.io.IOException("End of Stream on " + i + " - " + chunk + " returned from read");

}

return b;

}

public static int readInt(InputStream i) throws java.io.IOException {

byte[] b = readall(i,4);

int ij = (int) (((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff));

return ij;

}

public static void writeInt(OutputStream o, int i) throws java.io.IOException {

byte[] b = new byte[4];

b[0] = (byte)(0xff & (i >> 24));

b[1] = (byte)(0xff & (i >> 16));

b[2] = (byte)(0xff & (i >> 8));

b[3] = (byte)(0xff & i);

o.write(b);

}

public static void writeString(OutputStream o, String s) throws java.io.IOException {

byte[] b = s.getBytes();

writeInt(o,b.length);

o.write(b);

}

public static byte[] readArray(InputStream i) throws java.io.IOException {

int length = readInt(i);

if (length > 100000000)

throw new java.io.IOException("Outrageously large Object Size");

byte[] b = readall(i,length);

return b;

}

public static void writeArray(OutputStream o, byte[] b) throws java.io.IOException {

writeInt(o,b.length);

o.write(b,0,b.length);

}

The writer (client side) does this:

tcpServer.writeArray(bout, oshb);

tcpServer.writeArray(bout, osdb);

bout.flush();

and the reader (server side) does this:

byte[] oshb = readArray(bin);

byte[] osdb = readArray(bin);

And, a dozen or so times a day a get an extra byte that throws it out of whack.

I've not enabled Urgent Data on the read side -- I've set no special options.

Any ideas?

[3010 byte] By [javamc] at [2007-9-30 21:53:51]
# 1

Well, your readall() method is a bit messy (have a look at the readFully() method in DataInputStream for some inspiration), but I'd say the while statement should read

while (offset < cnt)

and next time please use formating tags: http://forum.java.sun.com/features.jsp#Formatting

BickelT at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...
# 2

Thanks BickelT -- but the while statement is correct -- the first element in the byte array is at index=0.

I definitely want to stop when the next byte to be read is at size - 1.

And please remember, this code is in production and works well for millions and millions of bytes every day. I only get failure about a dozen times a day over thirty connected nodes.

javamc at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...
# 3
Think about it, your code will fail only if there is exactly 1 byte left to read, which probably does not happen too often.You could also change it towhile(residual > 0)
BickelT at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...
# 4
OOPS -- you nailed it! What a dummy I am.Thanks for your help.
javamc at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...
# 5

I would also point you at the following which you should be using instead of rolling your own:

DataInputStream.readFully()

DataInputStream.readInt()

DataOutputStream.writeInt()

They do the same things as yours but without the bugs, and nobody is going to come along next year and break them for you ...

ejp at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...
# 6
Thanks to all for your help. And I have replaced my crude attempts with DataInput/Output Streams and methods.
javamc at 2007-7-7 3:22:01 > top of Java-index,Archived Forums,Socket Programming...