读取文件时IndexOutOfBoundException

时间:2012-03-07 15:53:58

标签: java sockets exception networking inputstream

我正在研究TFTP服务器应用程序。我成功地处理了从服务器到客户端的成功文件传输,但另一方面却被窃听。

客户端而不是传输整个文件只是终止whit编译器返回没有错误。调试器在标记的代码上显示IOBE异常,指的是数组超出范围。

整个转移过程如下:

  1. 客户端传输文件名和请求的操作WRQ - 写请求
  2. 如果WRQ为新文件指定了适当的名称,则服务器收到数据包并确定操作。
  3. 服务器现在开始执行receiveData(),直到它获得一个数据包< 512 indicationg EOT
  4. 客户端不断传输从文件中读取的数据。
  5. 密码:

    客户端:

    private void sendWRQ() throws Exception
    {
        String rrq = "WRQ-" + data;
        outgoingData = rrq.getBytes();
    
        DatagramPacket output = new DatagramPacket(outgoingData, outgoingData.length, serverAddress, serverPort);
        clientSocket.send(output);
        //Thread.sleep(50);
        sendData();
    }
    byte outgoingData = new byte[512];
    private void sendData() throws Exception
    {
        DatagramPacket dataTransfer = new DatagramPacket(outgoingData, outgoingData.length, serverAddress, serverPort);
        InputStream fis = new FileInputStream(new File(data));
    
        int x;
        while((x = fis.read(outgoingData,0,512)) != -1)  // << Debugged gives IOBE
        {
            dataTransfer.setLength(x);
            clientSocket.send(dataTransfer);
            Thread.sleep(5);
        }
    
        fis.close();
    }
    

    服务器:

    private void listen() throws Exception
    {
        DatagramPacket incTransfer = new DatagramPacket(incomingData, incomingData.length);
        serverSocket.receive(incTransfer);
    
        clientAddress = incTransfer.getAddress();
        clientPort = incTransfer.getPort();
    
        String output = new String(incTransfer.getData());
        if(output.substring(0, 3).equals("RRQ"))
        {
            File test = new File(output.substring(4));
            responseData = output.substring(4);
            if(test.exists())
            {
                sendResponse("Y");
            } else {
                sendResponse("N");
            }
        } else if (output.substring(0, 3).equals("WRQ"))
        {
            File test = new File(output.substring(4));
            if(test.exists())
            {
                Calendar cal = Calendar.getInstance();
                SimpleDateFormat prefix = new SimpleDateFormat(date_format);
                String date = prefix.format(cal.getTime()).toString();
    
                responseData = date + output.substring(4);
                receiveData();
            } else {
                responseData = output.substring(4);
                receiveData();
            }
        } 
    }
    
    
    private void receiveData() throws Exception
    {
        DatagramPacket receiveData = new DatagramPacket(incomingData, incomingData.length);
        OutputStream fos = new FileOutputStream(new File(responseData));
    
        while(true)
        {
            serverSocket.receive(receiveData);
            if(receiveData.getLength() == 512)
            {
                fos.write(receiveData.getData());
            } else {
                fos.write(receiveData.getData(), receiveData.getOffset(), receiveData.getLength());
                break;
            }
        }
        fos.close();
    }
    

2 个答案:

答案 0 :(得分:0)

唯一可能发生的方法是偏移或长度参数是否违反为InputStream.read(byte[], int, int)指定的约束;在这种情况下,缓冲区可能不是512字节长。在这种情况下,不需要指定第二个第三个参数,只需省略它们,然后在内部变为read(buffer, 0, buffer.length),这不会是错误的。

答案 1 :(得分:0)

好的,这是编码的方式,'outgoingData'字段是:

1)初始化为512

的长度

2)然后,在sendWRQ()中,'outgoingData'被重新初始化为rrq.getBytes()发回的任何内容。

3)然后,在sendData()中,'outgoingData'用作中间缓冲区,用于从文件中读取数据并将其放入dataTransfer对象中。

但是,由于'outgoingData'在步骤#2中被重新初始化,所以步骤#3中假设'outgoingData'仍然是512字节长度是假的。

因此,虽然EJP说使用read(outgoingData,0,outgoingData.length())是正确的,但是有一些架构问题,如果你解决,你将清除很多潜在的错误。

例如:

使用提供的代码,似乎没有理由在类级别声明outgoingData并在两个函数之间共享。根据应用程序的其余部分,这可能最终成为线程问题。 也许byte [] buffer = rrq.getBytes();在sendWRQ()和byte [] buffer = new byte [1024];在sendData()中。 此外,'data'参数是在类级别....出于什么原因?如果传入参数,可能会更好地被控制。

最后,我在网络环境中使用do {} while()循环运气不错。确保send()至少获得一次发送数据的机会,并使代码更具可读性。