Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 读取文件时发生IndexOutOfBoundException_Java_Sockets_Exception_Networking_Inputstream - Fatal编程技术网

Java 读取文件时发生IndexOutOfBoundException

Java 读取文件时发生IndexOutOfBoundException,java,sockets,exception,networking,inputstream,Java,Sockets,Exception,Networking,Inputstream,我正在开发一个TFTP服务器应用程序。我成功地处理了从服务器到客户机的文件传输,但另一方面却出现了错误 客户端没有传输整个文件,只是终止了whit编译器,没有返回任何错误。调试器在表示数组超出范围的标记代码上显示IOBE异常 整个转移过程如下所示: 客户端传输文件名和请求的操作WRQ-写入请求 服务器接收到数据包,并确定WRQ是否为新文件提供了适当的名称 服务器现在开始执行receiveData(),直到它得到一个数据包

我正在开发一个TFTP服务器应用程序。我成功地处理了从服务器到客户机的文件传输,但另一方面却出现了错误

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

整个转移过程如下所示:

  • 客户端传输文件名和请求的操作WRQ-写入请求
  • 服务器接收到数据包,并确定WRQ是否为新文件提供了适当的名称
  • 服务器现在开始执行receiveData(),直到它得到一个数据包<512表示EOT
  • 客户端不断传输从文件读取的数据
  • 关键代码:

    客户:

    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();
    }
    

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

    好的,按照编码方式,“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()中,字节[]缓冲区=新字节[1024];在sendData()中。 此外,“数据”参数位于类级别。。。。为什么?如果它是传入的参数,则可以更好地进行控制


    最后,我很幸运地在网络环境中使用了do{}while()循环。确保send()至少有一次机会发送数据,并使代码更具可读性。

    打印
    rrq.getBytes()
    ,然后查看它是否正确。不确定
    字符串
    是否正确处理特殊字符。它是正确的。问题不在此发送和接收此部分,因为它应该是有问题的部分,我在代码中标记了它。您没有提供
    outgoingData
    定义,它是否有足够的空间容纳512字节?byte[]outgoingData的大小是多少?我建议您创建一个新字节[],以便从FileInputStream读取。@Zaki您是对的。似乎一个新的byte[]数组解决了这个问题。
    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();
    }