📄 tftp.java
字号:
import java.net.*;
import java.io.*;
import java.util.*;
public class tftp {
static File f=null;
static int debug=2;
static int flag;//Print flag
//下载上传目录:
static String path="d://javawork//testfile//";
//端口号
static DatagramSocket ds;
static byte[] buf=new byte[516];
static DatagramPacket dp=new DatagramPacket(buf,516);
// 请求包的数据结构
static short opcode = 0;
static String filename=new String();
static String mode=new String();
// 数据包的数据结构
static short tftp_opcoded=3;
static Short blockd=1;
static String data=new String();
// ack包的结构
static Short blocka=0;
/*short tftp_opcodeq;*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//端口定义
ds=new DatagramSocket(69);
while(true){
//reset ...
blockd=1;
blocka=0;
for(;;){
//输入流
DataInputStream din = null;
ds.receive(dp);
buf = dp.getData();
din = new DataInputStream(new ByteArrayInputStream(buf));
//get operate code
opcode = din.readShort();
Println(debug,opcode,dp.getAddress(),flag);
//get filename
int foffset=2;//offset point to filename
int flen=0;//count the length of filename
while(din.readByte()!=0)
{
flen++; //filename will end with a null char('\0')
}
filename=new String(buf,foffset,flen);
//get the mode
int mdnoffset=foffset+flen+2;
int mdnlen=0;
while (din.readByte()!=0)
{
mdnlen++; //filename will end with a null char('\0')
}
mode = new String(buf,mdnoffset,mdnlen);
if(opcode==1){
RunRQ();//recieved read/download request.execute download method
break;//break for(;;) execute while();
}
else{//opcode==2
RunWQ();//recieved write/upload request.execute upload method
break;//break for(;;)
}//end branch(opcode==1)
}//end for(;;)
}//end while(); never break
}//end main()
public static void RunRQ() throws Exception{
flag=1;
long filepointer=1;
RandomAccessFile rf=null;
f=new File(path+filename);
if(f.exists()){//file is allowed to download
rf=new RandomAccessFile(f,"r");
long filelength=rf.length();//get the length of file
long num=filelength/512+1;//get the number of block will be send
//send data(1)
//输出流
ByteArrayOutputStream bag=new ByteArrayOutputStream();
DataOutputStream dout=new DataOutputStream(bag);
byte[] b=new byte[512];
dout.writeShort(3); //the opcode: data
dout.writeShort(blockd); //the block number
if(filepointer<num){
rf.seek((filepointer-1)*512);
rf.read(b);
dout.write(b);
//data=new String(b,0,512);
}else{
if(filepointer==num){
long len=filelength%512;
int lenint=(int)len;
byte[] b2=new byte[lenint];
rf.seek((filepointer-1)*512);
rf.read(b2);
dout.write(b2);
} else{
System.out.println("Download file "+filename+" sccuessful!");
rf.close();
return;
}
} //end check data(1) wether the last data packet,and data(1) was writen in DataOutputStream dout
rf.close();
//send data(1)
ds.send(new DatagramPacket(bag.toByteArray(), bag.size(),dp.getAddress(),dp.getPort()));
Println(debug,3,dp.getAddress(),flag);
//start receiving ack
for(;;){
rf=new RandomAccessFile(f,"r");
//输入流
DataInputStream din = null;
//输出流
ByteArrayOutputStream bag2=new ByteArrayOutputStream();
DataOutputStream dout2=new DataOutputStream(bag2);
ds.receive(dp);
buf = dp.getData();
din = new DataInputStream(new ByteArrayInputStream(buf));
opcode = din.readShort(); //得到操作码
Println(debug,opcode,dp.getAddress(),flag);
if(opcode==4)//if recieve ack
{
blocka=din.readShort(); //read block of ack
//if(blocka==9)blockd--;
if(blockd.equals(blocka)){//copare with block data.if equal to block of data which sended,blockd++ ready to send next data
if(blockd==32767){//block最大表示范围
blockd=1;
}else{
blockd++;
}//end check blockd==32767
filepointer++;//文件指针下移
}//end blockd.equals(blocka)
//send data
dout2.writeShort(3); //the opcode: data
dout2.writeShort(blockd); //the block number
if(filepointer<num){
rf.seek((filepointer-1)*512);
rf.read(b);
dout2.write(b);
//data=new String(b,0,512);
}else{
if(filepointer==num){
rf.seek((filepointer-1)*512);
long len2=filelength%512;
int lenint2=(int)len2;
byte[] b2=new byte[lenint2];
rf.read(b2);
dout2.write(b2);
} else{
System.out.println("Download file "+filename+" sccuessful!");
rf.close();
return;
}
} //end check data(blockd) wether the last data packet,and data(blockd) was writen in DataOutputStream dout
rf.close();
//send data(blockd)
ds.send(new DatagramPacket(bag2.toByteArray(), bag2.size(),dp.getAddress(),dp.getPort()));
Println(debug,3,dp.getAddress(),flag);
}//end if(opcode==4)
else{//opcode=1 data(1) is still in bag
ds.send(new DatagramPacket(bag.toByteArray(), bag.size(),dp.getAddress(),dp.getPort()));
Println(debug,3,dp.getAddress(),flag);
}
}//end for(;;)
}else{//file is not exists ,can't download
String ErrMsg="error:file not found";
int value=1;
SendError(value,ErrMsg,dp.getAddress(),dp.getPort());
}//end of check whether file is exist
return;
}//end RunRQ
public static void RunWQ()throws Exception{
flag=0;
long filepointer=0;
RandomAccessFile wf=null;
f=new File(path+filename);
if(!f.exists()){//file is allowed to upload
//send ack(0)
SendAck(blocka,dp.getAddress(),dp.getPort());
Println(debug,4,dp.getAddress(),flag);
//waiting to receive packet(data or write request)
for(;;){
// 输入流
DataInputStream din = null;
buf = dp.getData();
din = new DataInputStream(new ByteArrayInputStream(buf));
//receive packet
ds.receive(dp);
//timeout doesn't occur,so received the packet,get operate code
//get operate code
opcode = din.readShort();
Println(debug,(int)opcode,dp.getAddress(),flag);
if(opcode==3){//packet is data packet
//read data
blockd=din.readShort(); //read block of data
byte[] bufdata=new byte[512];
din.read(bufdata);//read data
data=new String(bufdata);
blockd--;
if(blocka.equals(blockd)){//copare with block data.if equal to block of data which recieved,resend this ack,else ready to recieve next data
//blocka++ filepointer++
blocka++;
filepointer++;
if(blocka==1){//createfile
//create file
f.createNewFile();
//write file
try{
wf=new RandomAccessFile(f,"rw");
}
catch (FileNotFoundException ex) {
break ;
}
wf.write(bufdata);
//send ack
SendAck(blocka,dp.getAddress(),dp.getPort());
Println(debug,4,dp.getAddress(),flag);
if(dp.getLength()<512){//the last packet
System.out.println("Host send last ack:"+blocka);
System.out.println("Upload file "+filename+" sccuessful!");
break;
}//end check last packet
//if dp.getLength()=512
}//end blocka==1;
else{//blocka>1
//write file
try{
wf=new RandomAccessFile(f,"rw");
}
catch (FileNotFoundException ex) {
break ;
}
wf.seek((filepointer-1)*512);
wf.write(bufdata);
//send ack
SendAck(blocka,dp.getAddress(),dp.getPort());
Println(debug,4,dp.getAddress(),flag);
if(dp.getLength()<512){
System.out.println("The last block of data is:"+blocka);
System.out.println("Upload file"+filename+"sccuessful!");
break;
}//end check last packet
//if dp.getLength()==512
}//end check block==1
}//recieved right data,write it in file.可以发送ack了
}else{//packet is write request packet,that means ack(0) was lost,so send ack(0) again.
SendAck(blocka,dp.getAddress(),dp.getPort());
Println(debug,4,dp.getAddress(),flag);
}//end check opcode(data or write request)
}//end for(;;)
}else{//file already exists
String ErrMsg="error:file already exists";
int value=6;
SendError(value,ErrMsg,dp.getAddress(),dp.getPort());
}//end check file
return;
}//end RunRQ
public static void SendAck(short blockack,InetAddress addr,int port)throws Exception{
// 输出流
ByteArrayOutputStream bag=new ByteArrayOutputStream();
DataOutputStream dout=new DataOutputStream(bag);
dout.writeShort(4);
dout.writeShort(blockack);
byte[] bufack=bag.toByteArray();
DatagramPacket ackpacket = new DatagramPacket(bufack,bufack.length,addr,port);
ds.send(ackpacket);
}//end SendAck
public static void SendError(int value,String Msg,InetAddress addr,int port)throws Exception{
ByteArrayOutputStream bag=new ByteArrayOutputStream();
DataOutputStream dout=new DataOutputStream(bag);
dout.writeShort(5);
dout.writeShort(value);
dout.write(Msg.getBytes());
dout.writeByte(0); //end of the ErrMsg
byte[] bufERROR = bag.toByteArray();
//construct a UDP packet
DatagramPacket dpError = new DatagramPacket(bufERROR,bufERROR.length,addr,port);
ds.send(dpError);
if(debug==2||debug==1)
System.out.println("Error "+Msg);
}//end SendError
public static void Println(int debug,int opcode,InetAddress addr,int flag){//flag=0 uploader receive data send ack;flag=1,download send data receive ack
if(opcode==1){
System.out.print(new Date());
System.out.println(" receive RRQ from "+addr.toString());
}
if(opcode==2){
System.out.print(new Date());
System.out.println(" receive WRQ from "+addr.toString());
}
if(opcode==3&&flag==0&&debug==2){
System.out.print(new Date());
System.out.println(" receive DATA from "+addr.toString());
}
if(opcode==3&&flag==1&&debug==2){
System.out.print(new Date());
System.out.println(" send DATA to"+addr.toString());
}
if(opcode==4&&flag==0&&debug==2){
System.out.print(new Date());
System.out.println(" send ACK to "+addr.toString());
}
if(opcode==4&&flag==1&&debug==2){
System.out.print(new Date());
System.out.println(" receive ACK from "+addr.toString());
}
}//end Println();
}//end class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -