📄 tftpclientagent.java
字号:
/*
* tftpClientAgent.java
*
* Created on 2007年4月29日, 上午9:31
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package tftpd;
import java.net.*;
import java.io.*;
/**
*
* @author Administrator
*/
public class tftpClientAgent extends Thread {
/** Creates a new instance of tftpClientAgent */
public tftpClientAgent(InetAddress ip, int port, short opcode, String fname, String mode) {
this.m_ClientAddress = ip;
this.m_ClientPort = port;
this.m_curopcode = opcode;
this.m_filename = fname;
this.m_mode = mode;
}
public void run() {
int nfail = 100;
while (nfail-- > 0) {
//try getFreePort 100 times
try {
this.m_so_tftp = new DatagramSocket(this.getFreePort());
break; //get a random port number
} catch (SocketException e) {
}
}
//ok, the UDP socket is ready, response to the client
switch (this.m_curopcode) {
case 1:
//RRQ
this.RRQ();
break;
case 2:
//WRQ
this.WRQ();
//System.out.println("debug: tftpClientAgent.run() --> a WRQ ended ...");
break;
}
this.m_so_tftp.close();
}
public void RRQ() {
int ntimeout = this.m_MAX_nTimeOut;
try {
short nblock = 1;
//send the #0 block ACK to start the transfer
if (!this.SendFile(nblock, this.m_filename, this.m_mode)) {
this.SendERROR((short)0, "无法读取文件");
return ;
}
//wait for the ACK packet
while (ntimeout > 0) {
DatagramPacket dp;
dp = this.waitForData();
if (dp == null) {
//this.SendERROR((short)0, "超时了,连接被服务器断开 ...");
//System.out.println("debug: tftpClientagent.RRQ() --> timeout: " + ntimeout);
ntimeout--;
} else {
//ok, get a packet, check the ip and port
if (!((dp.getAddress().equals(this.m_ClientAddress))
&& (dp.getPort() == this.m_ClientPort))) {
//ip or port has a mistake
//this.SendERROR((short)0, "我不认识你");
//System.out.println("debug: RRQ() --> ip or port error ...");
ntimeout--;
} else { //right ip and port
//get the opcode
DataInputStream din = new DataInputStream(new ByteArrayInputStream(dp.getData()));
int opcode = din.readShort();
//System.out.println("debug: the opcode is " + opcode);
if (opcode != 4) {
//不是04号ACK包
if (opcode == 1 && nblock == 1) {
//是01号RRQ包,且正在等待#1号ACK包
//此时收到RRQ,说明#1号data有可能失败了,重发
if (!this.SendFile(nblock, this.m_filename, this.m_mode)) {
this.SendERROR((short)0, "无法读取文件");
return ;
}
} else {
this.SendERROR((short)4, "非法的TFTP操作");
}
ntimeout--;
} else { //is an ACK packet
//System.out.println("debug: get a ACK packet");
int nblk = din.readShort();
//System.out.println("debug: the waiting for #" + nblock + " -- the curBlock is #" + nblk);
if (nblk != nblock) {
//System.out.println("debug: re-SendFile(" + nblock + ")");
//不是期待的块号,重发data包,超时计数减1
if (!this.SendFile(nblock, this.m_filename, this.m_mode)) {
this.SendERROR((short)0, "无法读取文件");
return ;
}
ntimeout--;
} else { //get the right ACK packet
//the rest of the special file
long restSize = this.getRestOfFile(nblock, this.m_filename);
//System.out.println("debug: the restSize = " + restSize);
if (restSize < 0) {
//ok, 上次已经把剩余的发送完毕了,结束
ntimeout = 0;
} else {
//send the next block data
nblock++;
//System.out.println("debug: start sending ...");
if (!this.SendFile(nblock, this.m_filename, this.m_mode)) {
//System.out.println("debug: ERROR while sending the #" + nblock);
this.SendERROR((short)0, "无法读取文件");
ntimeout = 0;
} else {
//send succ
//System.out.println("debug: send the #" + nblock);
ntimeout = this.m_MAX_nTimeOut; //重置超时记数
//continue wait for ACK of the current block
}
}
}
}
}
}
}
} catch (Exception e) {
//System.out.println("Exception in tftpClientAgent.RRQ() --> " + e.getMessage());
}
}
public void WRQ() {
int ntimeout = this.m_MAX_nTimeOut;
try {
short nblock = 0;
//send the #0 block ACK to start the transfer
this.SendACK(nblock++);
//wait for the data packet
while (ntimeout > 0) {
DatagramPacket dp;
dp = this.waitForData();
//dp = new DatagramPacket(buf, 516);
if (dp == null) {
//this.SendERROR((short)0, "超时了,连接被服务器断开 ...");
//System.out.println("debug: tftpClientagent.WRQ() --> timeout: " + ntimeout);
ntimeout--;
} else {
//ok, get a packet, check the ip and port
if (!((dp.getAddress().equals(this.m_ClientAddress))
&& (dp.getPort() == this.m_ClientPort))) {
//ip or port has a mistake
//this.SendERROR((short)0, "我不认识你");
//System.out.println("debug: ip or port error ...");
ntimeout--;
} else { //right ip and port
//get the opcode
DataInputStream din = new DataInputStream(new ByteArrayInputStream(dp.getData()));
int opcode = din.readShort();
//System.out.println("debug: the opcode is " + opcode);
if (opcode != 3) {
//不是03号data包
if (opcode == 2 && nblock == 1) {
//是02号WRQ包,且正在等待#1号data包
//此时收到WRQ,说明#0号ACK有可能失败了,重发
this.SendACK((short)(nblock-1));
} else {
this.SendERROR((short)4, "非法的TFTP操作");
}
ntimeout--;
} else { //data packet
//System.out.println("debug: get a data packet");
int nblk = din.readShort();
//System.out.println("debug: the waiting for #" + nblock + " -- the curBlock is #" + nblk);
if (nblk != nblock) {
//System.out.println("debug: re-SendACK(" + (nblock-1) + ")");
//不是期待的块号,重发上一个包的ACK,超时计数减1
this.SendACK((short)(nblock-1));
ntimeout--;
} else { //the right packet waiting for
//this.SaveFile(this.m_filename);
if (!this.SaveFile(nblock, dp, this.m_filename, this.m_mode)) {
ntimeout = 0;
this.SendERROR((short)3, "磁盘满或超过分配的配额");
} else {
//send the current block ACK
this.SendACK(nblock);
//System.out.println("debug: dp.length = " + (dp.getLength()-4));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -