检测DataInputStream流的结尾

The*_*Guy 1 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
    }
}
Run Code Online (Sandbox Code Playgroud)

Gre*_*pff 5

你的理解read(byte[])是不正确的.它没有在数组中设置值-1.

Javadoc说:

返回: 读入缓冲区的总字节数,或者-1由于已到达流末尾而没有更多数据.

您需要检查返回值:

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

另外,即使只是正常读取数据,也需要检查读取的字节数是否是您请求的字节数.调用read不能保证实际填充您的数组.

您应该看一下readFully()哪个读取完全,并抛出一个EOFException结束流:

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

  • b.length 输入数据的字节是可用的,在这种情况下,进行正常的返回.
  • 检测到文件结尾,在这种情况下EOFException抛出一个文件.
  • 发生I/O错误,在这种情况下,IOException比其它EOFException异常.