检测DataInputStream流的结尾

时间:2015-06-26 04:18:40

标签: java arrays networking packet datainputstream

我现在正在服务器上为游戏工作。服务器的数据包读取循环是阻塞的,并且通常等待直到接收到数据包以继续循环。但是,如果客户端断开连接,DataInputStream将返回单个字节(-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
    }
}

1 个答案:

答案 0 :(得分:5)

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

Javadoc说:

  

<强>返回:   读入缓冲区的总字节数,如果由于已到达流末尾而没有其他数据,则为-1

您需要检查返回值:

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

作为旁注,即使只是正常读取数据,也需要检查读取的字节数是否是您请求的字节数。对read的调用无法保证实际填充您的数组。

您应该查看完全阅读的readFully(),并为流的结尾抛出EOFException

  

从输入流中读取一些字节并将它们存储到缓冲区数组b中。读取的字节数等于b的长度。   此方法将阻塞,直到出现以下某种情况:

     
      
  • b.length个字节的输入数据可用,在这种情况下可以正常返回。
  •   
  • 检测到文件结尾,在这种情况下会抛出EOFException
  •   
  • 发生I / O错误,在这种情况下会抛出IOException以外的EOFException
  •