Written on a few months, I changed today, only the server side.
reference:
TFTP protocol specification
TFTPSERVER.JAVA
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 370371372373374375376377378379380381382383384385386387388389 / * * Create Date 2004-8-30-11: 31: 14 * * / package starfire.tftp; import java.net *; import java.io. *; import java.util *; / ** *.. TFTP protocol specification * @Author starfire * * / public class TFtpServer extends Thread {public static final int DEFAULT_PORT = 69; private HashMap map = new HashMap (); private File root; private int port = DEFAULT_PORT; private DatagramSocket ds; private Timer Timer = new Timer (TRUE); public tftpserver () {this (".");
} Public tftpserver (string rootpath, int port) {this (rootpath); this.port = port;} public tftpserver (string rootpath) {this.root = new file (rootpath); try {this.root = this.root. getCanonicalFile ();} catch (IOException e) {e.printStackTrace ();}} public void run () {try {ds = new DatagramSocket (new InetSocketAddress (port));} catch (SocketException e) {System.out. Println ("Error When Create DataGram Socket: E.GetMessage ()); Return;} System.out.Println (" root path: " root.getPath ()); byte [] buf = new byte [516] DataGrampacket Packet = New DataGrampacket (BUF, 516); While (True) {Try {DS.Receive (Packet); System.Out.println ("Recv Packet:"); TFTPPACKETUTIL.DISPLAYBYTES (Packet.getData ()); // process (Packe T);} catch (ooException e1) {e1.printStackTrace ();}}} protected}}} protected}}} PROTECTED VOID Process (DataGrampacket Packet) {Try {byte [] buf = new byte [packet (packet) ()]; system.ArrayCopy. getData (), 0, buf, 0, buf.length); TFtpPacket tfp = TFtpPacketUtil.decode (buf); InetSocketAddress address = new InetSocketAddress (packet .getAddress (), packet.getPort ()); String key = address.getHostName () ":" Address.getPort (); System.out.println ("key =" key); system.out.println ("
Packet: " TFP); if (tfp.getoperatecode () == tftppacket.rrq || tfp.getoperatecode () == TFTPACKET.WRQ) {Client Client = New Client (Address); Boolean Result = Client.doAccept ((( RWPACKET) TFP); if (result) {map.put (key, client);}} else if (tfp.getoperatecode () == tftppacket.data) {Client Client = (client) map.get (key); if (client == null) {return;} boolean result = client.doprocess ((DataPacket) TFP); if (result) {map.remove (key); client.destroy ();}} else f (tfp.getoperatecode ) == TFTPPACKET.ACK) {Client Client = (client) map.get (key); if (client == null) {Return;} Boolean Result = Client.doprocess ((AC) Kpacket) TFP); if (result) {map.remove (key); client.destroy ();}} else if ()}} else f () == tftppacket.rror) {system.out.println (TFP); Client Client = (client) map.remove (key); client.destroy ();}} catch (badpacketformatexception e) {E.PrintStackTrace (); system.out.println ("Recv unknown packet.");}} protected Send (inetsocketaddress address, byte [] data) {datagrampacket packet =
New DataGrampacket (Data, Data.Length, Address .Getaddress (), address.get (); try {ds.send (packet); system.out.println ("Send Packet:"); TFTPPACKETUTIL.DISPLAYBYTES (DATA) ;} catch (IOException e) {e.printStackTrace ();}} class Client {public static final int DEFAULT_DATA_SIZE = 512; public static final int DEFAULT_TIME_OUT = 1000; private InetSocketAddress address; private String fileName; private int block; private boolean checked // Last package has received the response private randomaccessfile Raf; private boolean acceptfile = false; private bote [] buf = new byte [default_data_size]; private bote [] data; private int Times = 0; // Every few Reissue Private ResendTask Task; Public Client (InetSocketAddress Address) {this.address = address;} public void design {= f (task! = Null) { Task.cancel ();} if (raf! = null) {try {raf.close ();} catch (ioException e) {E.PrintStackTrace ();} raf = null;}} / ** * if accept, return true;. else return false * * @param packet * @return * / public boolean doAccept (RWPacket packet) {this.fileName = packet.getFileName (); if (accepted) {return true;} if (packet.getOperateCode ( ) ==
TFTPCKET.RRQ) {Try {file file = new file (root, filename); system.out.println (file.getpath () " file.exists ()); raf = new randomaccessfile (File," R " ); Data = new byte [default_data_size]; int size = raf.read (data); DataPacket DP = new datapacket (); dp.setblock (1); if (size! = Default_data_size) {byte [] buf = new Byte [size]; system.Arraycopy (data, 0, buf, 0, size); DATA = BUF;} DP.SETDATA (DATA); DATA = TFTPPACKETUTIL.Encode (DP); send (address, data); block = 1 Task = new resendtask (address, data); time.schedule (task, default_time_out);} catch (filenotfoundexception e) { System.out .println ("File:" E.GetMessage () "Not found."); ErrorPacket EP = New errorPacket (); EP.SETERRORCODE (ErrorPacket.File_not_Found_code); byte [] data = tftppacketututil.Encode EP); send (address, data); return false;} catch (ioException e) {E.PrintStackTrace ();}} else {file file = new file (root, filename); if (file.exists ()) { ErrorPacket EP = New ErrorPacket ();
EP.SETERRORCODE (ErrorPacket.File_exist_code); EP.SETERRORMESSAGE ("File:" FileName "HAS EXIST"); Byte [] Data = TFTPACKETIL.ETE (EP); Send (Address, Data); Return False;} Try {File.createnewfile (); raf = new randomaccessfile (file, "rException e) {system.out.println (" CREATE: " FileName " Failed. "); Errorpacket EP = New ErrorPacket (); EP.SETERRORCODE (ERRORPACKET.NOT_DEFINED_CODE); BYTE [] DATA = TFTPPACKETUTIL.Encode (EP); Return False;} Ackpacket AP = New Ackpacket (); ap.setblock (0) Data = TFTPPACKETUTIL.Encode (AP); SEND (Address, Data); Task = New Resendt ask (address, data); timer.schedule (task, DEFAULT_TIME_OUT);} accepted = true; return accepted;} / ** * if transfer end, return true, else return false * * @param packet * @return * /. Public Boolean Doprocess (Ackpacket Packet) {if (Task! = Null) {task.cancel (); task = null;} if (packet.getblock () == block) {try {ix (Raf == Null || RAF .length () <
= Block * DEFAULT_DATA_SIZE) {return true;} raf.seek (block * DEFAULT_DATA_SIZE); int size = raf.read (buf); data = buf; if (size NULL) {Try {Raf.Write (DATA);} catch (ooException e) {E.PrintStackTrace ();}} f (data == null || data.length ) .Start ();} / ** * @return * / public file getroot () {Return root;} / ** * @return * / public int GETPORT () {return port;} / ** * @Param I * / Public void setport (INT i) {port = i;}} TFTPPACKETUTIL.JAVA / * * Create Date 2004-8-30-12: 49: 20 * * / package starfire.tftp; / ** * @Author Starfire a > * / Public final class tftppacketutus {private tftppacketututil () {} public static tftppacket decode (Byte [] BUF) THROWS BadPacketFormatException {if (buf == null || buf.length <4) {throw new BadPacketFormatException ( "packet too small");} int operateCode = buf [1]; if (operateCode } / ** * 2 Bytes 2 bytes string 1 byte * ------------------------------------- ---- * | opcode | ErrorCode | Errmsg | 0 | * ----------------------------------- ------ * / private static TFtpPacket decodeERRORPacket (byte [] buf) throws BadPacketFormatException {if (buf.length <4) {throw new BadPacketFormatException ( "ack packet must> = 4 bytes");} ERRORPacket packet = new ErrorPacket (); packet.setOperatecode (tftppacket.error); packet.seterrorcode (BUF [2] << 8 BUF [3]); int end = 4; int = 4; for (; i } / ** * 2 Bytes 2 bytes n bytes * --------------------------------- * | opcode | Block # | data | * --------------------------------- * @Param buf * @return * / private static TFtpPacket decodeDATAPacket (byte [] buf) throws BadPacketFormatException {if (buf.length <4) {throw new BadPacketFormatException ( "bad data packet");} dATAPacket packet = new dATAPacket (); packet.setOperateCode (TFtpPacket.DATA); Packet.setblock (BYTE2INT (BUF [2]) * 256 byte2int (BUF [3])); //system.out.println ("Decode Data Packet, Block:" Packet.getBlock ()); byte [] Data = new byte [buf.length-4]; System.Arraycopy (BUF, 4, DATA, 0, DATA.LENGTH); Packet.SetData (DATA); return packet;} private static int Byte2int ((b & 0x80)! = 0) {RETURN 128 (B & 0x7F);} else {return b;}} / ** * RRQ, WRQ Packet Format * 2 bytes string 1 byte string 1 byte * ------- ----------------------------------------- * | Opcode | filename | 0 | MODE | 0 | * ------------------------------------- ----------- * @Param buf * @return * / private static tftppacket decoderwpacket (Byte [] BUF) throws badpacket form = new rwpacket (); packet (); packet.setoperatecode ((int) buf [ 1]); int start = 2; int end = 2; INT i; for (i = start; i For (i = start; i Packet.getblock (); buf [2] = (Byte) ((BLOCK >> 8) & 0xff); BUF [3] = (Byte) (BLOCK & 0xFF); Return BUF;} / ** * @Param Packet * @Return * / Private static Byte [] encodeData Packet "{byte [] data = packet.getdata (); int size = 2 2; if (data! = Null) {size = data.length;} byte [] BUF = new byte [size]; system.out.println ("Encode data packet, buf [0] =" integer.toHexString (BUF [0])); buf [1] = (byte) (TFTPPACKET.DATA & 0xFF) INT block = packet.getblock (); buf [2] = (Byte) (BLOCK >> 8) & 0xFF); BUF [3] = (Byte) (block & 0xff); if (data! = Null) {system. ArrayCopy (Data, 0, BUF, 4, DATA.LENGTH);} Return BUF;} / ** * @Param Packet * @Return * / Private Static Byte [] encoderwpacket (rwpacket packet) {int operatecode = packet.getoperatecode ); Int size = 2; string filename = packet.getFileName (); string mode = packet.getmode (); byte [] nameBytes = filename.getbytes (); // filename must not n ULL SIZE = NameBytes.Length 1; Byte [] modebytes = null; if (mode! = null) {ModeBytes = mode.getbytes (); size = modebets.length 1;} Byte [] buf = new byte [size]; buf [1] = (Byte); System.ArrayCopy (Namebytes, 0, BUF, 2, NameBytes.length); if (Modebytes! = null) {INT POS = 2 NameBytes.length 1; System.ArrayCopy (Modebytes, 0, BUF, POS, MODEBYTES.LENGTH);} Return BUF;} static int count = 0; public static void displaybytes (byte [] buf) {Count ; If (buf == null) {system.out.println (count ": " null); return;} StringBuffer SB = new stringbuffer (); int Len = buf.length> 10? 10: buf. Length; for (INT i = 0; I 01234567891011121314151617181920212223242526272829303132 / * * Create Date 2004-8-30-11: 34: 03 * * / package starfire.tftp; / ** * @author starfire a> * * / public abstract class TFtpPacket {public static final int UNKNOWN = 0; // unknown public static final int RRQ = 1; // read request public static final int WRQ = 2; // write request public static final int DATA = 3; // data public static final int ACK = 4; // Acknowledgment public static final int eRROR = 5; // error private int operateCode = UNKNOWN; public int getOperateCode () {return operateCode;} / ** * @param i * / public void setopratecode (int i) {operatecode = i;}} BadpacketFormatexception.java 01234567891011121314151617181920 / * * Creation date 2004-8-30-11: 54: 24 * * / package starfire.tftp; / ** * @Author Starfire A> * / public class badpacketformatexception extends Exception {public badpacketformatexception () {super ();} public badpacketformatexception (String msg) {super (msg);}} RWPACKET.JAVA 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 / * creation date 2004-8-30-11: 51: 16 * * / package starfire.tftp; / ** * @author starfire a> * * / public class RWPacket extends TFtpPacket {private String fileName; private String mode; public RWPacket () {} / ** * @return * / public String getFileName () {return fileName;} / ** * @return * / public String getMode () {return mode;} / ** * @param string * / public void setFileName (String string) {fileName = string;} / ** * @param string * / public void setMode (String string) { Mode = string;} public string toString () {return (Getoperatecode () == TFTPPACKET.RRQ? "Read Packet:": "Write Packet:") "[filename: =" filename "] [Mode =" Mode "]";}} errorpacket.java 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 / * * Create Date 2004-8-30-13: 07: 55 * * / package starfire.tftp; / ** * @author starfire a> * / public class errorpacket extends tftppacket {/ ** * error code * Value meaning * 0 Unexpected, see Error message (if prompted this information) * 1 File Did not find * 2 Access illegal * 3 disk full Or exceed the assigned quota * 4 illegal TFTP operation * 5 Unknown transmission ID * 6 file already exists * 7 Nothing users * / public static final int not_defined_code = 0; public static final int file_not_found_code = 1; public static final int int INT ILLEGAL_ACCESS_CODE = 2; public static final int DISK_FULL_CODE = 3; public static final int ILLEGAL_OPERATE_CODE = 4; public static final int UNKNOWN_ID_CODE = 5; public static final int FILE_EXIST_CODE = 6; public static final int USER_NOT_EXIST_CODE = 7; private int errorCode; private String ErrorMessage; Public ErrorPacket () {setopratecode (TFTPP Acket.error);} / ** * @return * / public int getErrorCode () {return error;} / ** * @return * / public string getErrorMessage () {Return ErrorMessage;} / ** * @Param i * / public void setErrorCode (int i) {errorCode = i;} / ** * @param string * / public void setErrorMessage (String string) {errorMessage = string;} public String toString () {return "Error packet: [errorCode = " ERRORCODE "] [ErrorMessage = " ErrorMessage "] ";}} DataPacket.java 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 / * * Create Date 2004-8-30-13: 04: 07 * * / package starfire.tftp; / ** * @author starfire a> * * / public class dATAPacket extends TFtpPacket {private int block; private byte [] data; public dATAPacket () {setOperateCode (TFtpPacket.DATA);} / ** * @return * / public int getBlock () {return block } / ** * @Return * / public byte [] getdata () {returnction data;} / ** * @Param block * / public void setblock (int block) {this.block = block;} / ** * @Param data * / public void setdata (byte [] data) {this.data = data;} public string toString () {return "data packet: [block =" block "] [data size =" (data = = NULL? 0: Data.length) "]";}} Ackpacket.java 01234567891011121314151617181920212223242526272829303132333435 / * * Create Date 2004-8-30-13: 05: 47 * * / package starfire.tftp; / ** * @author starfire a> * * / public class ACKPacket extends TFtpPacket {private int block; public ACKPacket () {setOperateCode (TFtpPacket.ACK);} / ** * @return * / public int getBlock () {return block;} / ** * @Param i * / public void setblock (int i) {block = i;} public string toString () {return "ACK PACKET: [block =" block "]";}}