Detect DataInputStream end of stream

5.1k views Asked by At

I'm working on the server for a game right now. The server's packet reading loop is blocking, and typically waits until a packet is received to continue through the loop. However, if the client disconnects, the DataInputStream returns a single byte (-1) and the loop is executed in rapid succession, as is expected. However, I don't use the DataInputStream's read() method to read one byte at a time, I use the read(byte[]) method to read them all at once into a byte array. As such, I can't easily detect if the stream is returning a single byte valued at -1.

Possible Solution: I could check if the first byte of the array is -1, and if so loop through the array to see if the rest of the array is nothing but zeroes. Doing this seems extremely inefficient however, and I feel that it would affect performance as client count increases.

Here's a simplified version of my packet-reading loop:

while (!thread.isInterrupted() && !isDisconnected())
{
    try
    {
        byte[] data = new byte[26];
        data = new byte[26];

        input.read(data);

        //Need to check if end of stream here somehow
        Packet rawPacket = Packet.extractPacketFromData(data); //Constructs packet from the received data

        if(rawPacket instanceof SomePacket)
        {
            //Do stuff with packet
        }
    }
    catch(IOException e)
    {
        disconnectClient(); //Toggles flag showing client has disconnected
    }
}
1

There are 1 answers

0
Greg Kopff On BEST ANSWER

Your understanding of read(byte[]) is incorrect. It doesn't set a value in your array to -1.

The Javadoc says:

Returns: the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.

You need to check the return value:

int bytesRead = input.read(data);
if (bytesRead == -1)
{
  // it's end of stream
}

As a side note, even when just reading data normally, you do need to check the number of bytes read was the number of bytes you requested. The call to read is not guaranteed to actually fill your array.

You should take a look at readFully() which does read fully, and throws an EOFException for end of stream:

Reads some bytes from an input stream and stores them into the buffer array b. The number of bytes read is equal to the length of b. This method blocks until one of the following conditions occurs:

  • b.length bytes of input data are available, in which case a normal return is made.
  • End of file is detected, in which case an EOFException is thrown.
  • An I/O error occurs, in which case an IOException other than EOFException is thrown.