Tuesday, November 25, 2008

TFTP server for Java

TFTP server :

I have searched in goole about TFTP server. I have collected and created a simple TFTP server implementation to solve my problem.

TFTP server uses UDP protocol and consumes 69 port. This TFTP server extends from TFTPClient.. No bother just here I used get get and put methods. We can directly use TFTP.

We need to download
"org.apache.commons.net.tftp" package to implement TFTP Server
Just try this code. Which will send file to remote system.



import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;


import org.apache.commons.net.tftp.TFTPClient;
import org.apache.commons.net.tftp.TFTPDataPacket;
import org.apache.commons.net.tftp.TFTPPacket;
import org.apache.commons.net.tftp.TFTPRequestPacket;

public class TFTPServer extends TFTPClient implements Runnable
{
public void run ()
{
try
{

open(69, java.net.InetAddress.getByName(null));
while (true)
{
checkForRequests();
}

}
catch (Exception e)
{

e.printStackTrace();
}

beginBufferedOps();
}

public TFTPServer()
{

}

public static byte[] getBytesFromFile (File file) throws IOException
{
InputStream is = new FileInputStream(file);

// Get the size of the file
long length = file.length();

// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE)
{
// File is too large
}

// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];

// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < numread =" is.read(bytes,">= 0)
{
offset += numRead;
}

// Ensure all the bytes have been read in
if (offset < bytes.length)
{
throw new IOException("Could not completely read file " + file.getName());
}

// Close the input stream and return bytes
is.close();
return bytes;
}

/**
* Sends a bogus file to the TFTP client, and prints a message on the screen.
*
* @param addr
* Address to send to
* @param port
* Port to send to
*/
private void sendFile (File file, InetAddress addr, int port)
{
try
{

int bytesSent = 0;
int blockNum = 1;
byte[] inputBuf = getBytesFromFile(file);
while (bytesSent < inputBuf.length)
{
/*
* Note: this loop assumes that the buffer does not end on an
* exact 512 byte boundary! If it did, you would need to send an
* extra zero-length data packet at the end. As it is, the
* less-than-512 packet signifies that it is the end.
*/

// send a data packet with the next bytes from our "file"
int toSend = 512;
if (bytesSent + 512 > inputBuf.length)
{
toSend = inputBuf.length - bytesSent;
}

TFTPDataPacket dPack = new TFTPDataPacket(addr, port, blockNum, inputBuf, bytesSent, toSend);
send(dPack);

blockNum++;
bytesSent += toSend;

// get acknowledgement packet
TFTPPacket pack = receive();

/*
* Verify it is a acknowledge packet -- Note: should check some
* other things, like it being the correct block number.
*/
if (pack.getType() != TFTPPacket.ACKNOWLEDGEMENT)
{
// printPacketError( pack, "read file request" );
return;
}
} // end of while loop sending file

System.out.println("File sent successfully");
}
catch (Exception e)
{
System.out.println("Exception in sending file: " + e.getMessage());
}
}

public void checkForRequests ()
{
TFTPPacket pack = null;
try
{
pack = receive();
}
catch (Exception e)
{
/*
* Normally this should mean a timeout occurred -- do nothing, and
* return. In a real application, should check the exception type!
*/
return;
}

// check packet type and send/receive file
try
{
switch (pack.getType())
{
case TFTPPacket.READ_REQUEST:
TFTPRequestPacket rPack = (TFTPRequestPacket) pack;
System.out.println("Read request received for file " + rPack.getFilename() + " from address " + rPack.getPort());
File file = new File("c:\\" + rPack.getFilename());
InputStream is = new BufferedInputStream(new FileInputStream(file));
this.sendFile(file, pack.getAddress(), pack.getPort());
break;

case TFTPPacket.WRITE_REQUEST:
TFTPRequestPacket wPack = (TFTPRequestPacket) pack;
System.out.println("Write request received for file " + wPack.getFilename() + " from address " + wPack.getPort());
// receiveFile( pack.getAddress(), pack.getPort() );
break;

default:
// printPacketError( pack, "checking for requests" );
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* @param args
*/
public static void main (String[] args)
{
TFTPServer test = new TFTPServer();
try
{

test.open(69, java.net.InetAddress.getByName(null));
while (true)
{
test.checkForRequests();
}
//test.receive();
// TFTPdata data;

}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

test.beginBufferedOps();
}

}

6 comments:

Unknown said...

hey thanks...ths code helped me..!!

Marco Paulo Ollivier said...
This comment has been removed by the author.
Marco Paulo Ollivier said...

I'd like to thank you.
this code was very useful for me.
just a comment, I think that a piece of your code is incomplete.

while (offset < numread =" is.read(bytes,">= 0){
}

i did this way...

while(offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length-offset)) >= 0){}

that's ok?

Thanks one more time and see you...

Shiv Modi said...

Hi, I'm new to java. Can you please let me know how many and which arguments i have to pass at run time to make it working?

Unknown said...

Hi. Where can i take the org.apache.commons.net.tftp
and how can i implement it ??? =(

Dimitri said...

To download commons-net go here:
http://commons.apache.org/proper/commons-net/download_net.cgi