【问题标题】:Detect DataInputStream end of stream检测 DataInputStream 流的结尾
【发布时间】:2015-06-26 04:18:40
【问题描述】:

我现在正在服务器上开发一款游戏。服务器的数据包读取循环是阻塞的,通常会等到接收到数据包才能继续循环。但是,如果客户端断开连接,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
    }
}

【问题讨论】:

  • 你应该看看readFully btw。

标签: java arrays networking packet datainputstream


【解决方案1】:

您对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

【讨论】:

    猜你喜欢
    • 2015-05-08
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多