我正在制作TFTP应用程序。根据协议RFC,所有数据必须以最大大小的512字节块发送。因此每个数据包可以是<= 512字节。
我将每个文件读入一个byte [] outgoingData = new byte [512];数组,我发送给客户端,但是当它获得一个总大小小于512字节的文件,如ascii文件或.ini,.css,.html等时,似乎出现了问题。
奇怪的是,对于UDP协议,每次传输高达3mb已经过去而没有大的损失。似乎发生的唯一损失是读取的文件的最后一个块少于512个字节。
private void sendData() throws Exception
{
DatagramPacket data = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
InputStream fis = new FileInputStream(responseData);
int a;
while((a = fis.read(outgoingData,0,512)) != -1)
{
serverSocket.send(data);
Thread.sleep(5);
}
}
由于这是一个关于读取文件的问题,如何修复文件末尾的丢失以及不读取小于512的文件的问题
客户端:
private void receiveData() throws Exception
{
DatagramPacket receiveData = new DatagramPacket(incomingData, incomingData.length);
OutputStream fos = new FileOutputStream(new File("1"+data));
while(true)
{
clientSocket.receive(receiveData);
if(receiveData.getLength() == 512)
{
fos.write(incomingData);xx
} else {
fos.write(incomingData);
fos.close();
break;
}
}
clientSocket.close();
}
答案 0 :(得分:1)
您的数据包(data
)目前的固定长度为outgoingData.length
(512?)。因此,当您致电serverSocket.send(data)
时,它会发送outgoingData
数组中的所有数据。
问题是fis.read(outgoingData, 0, 512)
有时读取少于512字节的数据。这很可能发生在文件输入流的末尾,当时没有那么多数据需要读取。但它也可能更早发生(在实践中不太可能,但你仍然应该检查是否安全)。
您已经存储了a
中实际读取的字节数。只需将此号码传递给setLength
,以便DatagramSocket
知道只发送这么多数据。
这应该可以解决问题:
private void sendData() throws Exception
{
DatagramPacket data = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
InputStream fis = new FileInputStream(responseData);
int a;
while((a = fis.read(outgoingData,0,512)) != -1)
{
data.setLength(a);
// or this
//data = new DatagramPacket(outgoingData, a, clientAddress, clientPort);
serverSocket.send(data);
Thread.sleep(5);
}
}
接收:
private void receiveData() throws Exception {
DatagramPacket receiveData = new DatagramPacket(new byte[512], 512);
OutputStream fos = new FileOutputStream(new File("1"+data));
while (true) {
clientSocket.receive(receiveData);
if (receiveData.getLength() == 512) {
fos.write(receiveData.getData());
} else {
fos.write(receiveData.getData(), receiveData.getOffset(), receiveData.getLength());
break;
}
}
fos.close();
clientSocket.close();
}
答案 1 :(得分:1)
private void sendData() throws Exception
{
DatagramPacket data = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
InputStream fis = new FileInputStream(responseData);
int a;
while((a = fis.read(outgoingData,0,512)) != -1)
{
data.setLength(a); //'a' is the number of bytes read setLength(int) lets you set the length of bytes you want to sent
serverSocket.send(data);
Thread.sleep(5);
}
}
setLength(int) Method DatagramPacket 现在在接收端,你做这样的事情:
byte[]buffer = new byte[512];
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
while(socket.isBound() && !socket.isClosed()){
socket.receive(packet);
system.out.println("Packet Length: "+packet.getLength());
//code here
}
<强> FIX:强> 在Server.java中
private void sendResponse(String res) throws Exception
{
if(res.equals("Y"))
{
// Send ACK -> Send File
DatagramPacket x = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
serverSocket.send(x); //<<SEND ACK
sendData();
} else {
String error = "ERROR: The file you requested does not exist.";
outgoingData = error.getBytes();
DatagramPacket err = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
serverSocket.send(err);
}
}
我注意到你没有发送一个ack而客户端期待它,这似乎是你唯一的问题。第一个数据包目前没有为您服务。现在你只需要将ack数据包设置为你想要的。我刚发送它时它不包含字符串“ERROR”。