我正在研究TFTP服务器应用程序。我成功地处理了从服务器到客户端的成功文件传输,但另一方面却被窃听。
客户端而不是传输整个文件只是终止whit编译器返回没有错误。调试器在标记的代码上显示IOBE异常,指的是数组超出范围。
整个转移过程如下:
密码:
客户端:
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();
}
答案 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()至少获得一次发送数据的机会,并使代码更具可读性。