I am working with the DataInputStream.readFully method and trying to figure out the best way to handle the EOFException that is executed in this method. I am getting this log entry and could use some help trying to find out what the problem is as this exception does not appear to be handled and my problem is stuck in a loop with this same error. Any help/direction would be appreciated. Thank you.
TRACE | AccSysFNBBT-Socket-1-ReceiveQueuer-0 | com.sharpbancsystems.ATM.channel.ActiveSocket | 528 |2013-11-22 11:10:02,311| - Received 2 bytes:
S
INFO | AccSysFNBBT-Socket-1-ReceiveQueuer-0 | com.sharpbancsystems.ATM.channel.ActiveSocket | 455 |2013-11-22 11:10:02,312| - Received message, length is 2643
INFO | AccSysFNBBT-Socket-1-ReceiveQueuer-1 | com.sharpbancsystems.ATM.channel.ActiveSocket | 453 |2013-11-22 11:10:03,315| - Waiting for new message.
WARN | AccSysFNBBT-Socket-1-ReceiveQueuer-0 | com.sharpbancsystems.ATM.channel.ActiveSocket | 483 |2013-11-22 11:10:03,315| -
java.io.EOFException
java.io.DataInputStream.readFully(Unknown Source)
com.sharpbancsystems.ATM.channel.ActiveSocket.blockUntilGetMessageBytes(ActiveSocket.java:462)
com.sharpbancsystems.ATM.channel.ActiveSocket.blockUntilReceiveMessage(ActiveSocket.java:266)
com.sharpbancsystems.ATM.channel.ReceiveQueuer.run(ReceiveQueuer.java:113)
java.lang.Thread.run(Unknown Source)
Here is my code where this is occurring:
private byte[] blockUntilGetMessageBytes(final Request request, final ProcessingTimer timer) throws ChannelException {
byte[] data = null;
int len;
try {
// have to synchronize on the dataInputStream because the class was designed to have more than one ReceiveQueuer using this method
synchronized (dataInputStream) {
LOGGER.info("Waiting for new message.");
len = blockUntilGetMessageLength();
LOGGER.info("Received message, length is " + len);
if (!owningChannel.shouldTerminate) {
if (len > 0 && len <= 15000) {
request.setTimeStampDataFieldAsTimestamp(RequestConstants.SaveDataField.FromStartReceiveTMS);
timer.start();
data = new byte[len];
dataInputStream.readFully(data, 0, len);
LOGGER.trace("Full message: " + new String(data));
request.setTimeStampDataFieldAsTimestamp(RequestConstants.SaveDataField.FromFinishReceiveTMS);
timer.finish();
request.setNanosecondDataField(RequestConstants.SaveDataField.FromReceiveNS, timer.nanos());
if (channelStats != null) {
channelStats.addBytesReceived(data.length + 2); // include the 2 bytes for the length indicator
channelStats.increaseReceivedMsgs();
}
} else if (len == 0) {
// Should probably log it, but continue
LOGGER.info("Empty message received.");
throw new ChannelException(getBankID(), "Empty message received");
} else {
throw new ISOException("Invalid receive length: " + len + ".");
}
}
}
return data;
} catch (final Exception ex) {
LOGGER.warn(FormatData.fullStackTrace(ex));
throw new ChannelException(getChannelID().getNumericId(), this.getClass().getSimpleName().concat(".getMessageBytes()"), ex);
}
}
protected int blockUntilGetMessageLength() {
final byte[] b = new byte[2];
try {
dataInputStream.readFully(b, 0, 2);
} catch (final EOFException ex){
// ***** 20131022 MS - Per Shannon add getNeedReconnect() here. *****
getNeedReconnect().set(true);
socket.isConnected();
// ***** 20131022 MS - Per Shannon this means there was a premature EOF. *****
if (this.shouldTerminate) {
return 0;
} else {
synchronized (socket) {
socket.notify();
}
LOGGER.warn(FormatData.formatStack(ex));
}
} catch (final IOException ex) {
// ***** 20131022 MS - Per Shannon add getNeedReconnect() here. *****
getNeedReconnect().set(true);
socket.isConnected();
if (this.shouldTerminate) {
return 0;
} else {
synchronized (socket) {
socket.notify();
}
LOGGER.warn(FormatData.formatStack(ex));
return 0;
}
}
LOGGER.trace("Received 2 bytes: " + new String(b));
return ((((b[0]) & BYTEMASK) << BYTESHIFT) | ((b[1]) & BYTEMASK));
}
Best Solution
You get the exception, because
len
is greater than the number of bytes you can read from the stream. So apparentlyblockUntilGetMessageLength();
returns a bad value.Without knowing how you compute
len
, it's not possible to tell you how to really fix this. But in any case, you could simply do something like this:The method would return the number of bytes really read.