检测 DataInputStream 流的结尾

Detect DataInputStream end of stream

我正在为一个游戏开发服务器。服务器的数据包读取循环是阻塞的,通常会等到接收到数据包才能继续通过循环。但是,如果客户端断开连接,DataInputStream returns 一个字节 (-1) 并且循环会像预期的那样快速连续执行。但是,我不使用 DataInputStream 的 read() 方法一次读取一个字节,而是使用 read(byte[]) 方法一次将它们全部读取到一个字节数组中。因此,我无法轻易检测到流是否返回值为 -1 的单个字节。

可能的解决方案: 我可以检查数组的第一个字节是否为 -1,如果是,则遍历数组以查看数组的其余部分是否只是零。然而,这样做似乎效率极低,而且我觉得随着客户端数量的增加,它会影响性能。

这是我的数据包读取循环的简化版本:

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
    }
}

您对read(byte[])的理解有误。它不会将数组中的值设置为 -1

Javadoc 说:

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.

您需要检查 return 值:

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

附带说明一下,即使只是正常读取数据,您也需要检查读取的字节数是您请求的字节数。不能保证对 read 的调用实际填充您的数组。

您应该看一下 readFully(),它确实完全读取,并在流结束时抛出一个 EOFException

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.