📄 ftpconnection.java
字号:
package jftp;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
public class FtpConnection extends Thread //继承线程
{
static public String root = null; /** 主目录 */
private String currentDir = "/"; // 当前目录
private Socket socket; //客户套接字
private BufferedReader reader = null; //读入的字符缓冲区
private BufferedWriter writer = null; //写出的字符缓冲区
private String clientIP = null; //客户端IP地址
private Socket tempSocket = null; //tempSocket用于传送文件
private ServerSocket pasvSocket = null; //用于被动模式
private String host = null;
private int port = (-1);
public FtpConnection(Socket socket)
{
this.socket = socket;
this.clientIP = socket.getInetAddress().getHostAddress();//获取客户端IP地址
}
public void run()
{
String command;
try
{
System.out.println(clientIP + " 已连接 ");
socket.setSoTimeout(60000); //ftp超时设定
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//获取输入输出流
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
response("220-欢迎消息......"); //*****自定义
response("220-欢迎消息......"); //*****自定义
response("220 注意最后一行欢迎消息没有");
for(;;) //循环检测命令
{
command = reader.readLine(); //读入内容
if(command == null)
break;
System.out.println("命令来自 " + clientIP + " 命令为: " + command);
parseCommand(command); //*****自定义
if(command.equals("QUIT")) //收到QUIT命令
break;
}
}
catch(Exception e) { e.printStackTrace(); }
finally
{ try
{
if(reader!=null) reader.close(); //关闭输入流
}
catch(Exception e) {}
try
{
if(writer!=null) writer.close(); //关闭输出流
}
catch(Exception e) {}
try
{
if(this.pasvSocket!=null) pasvSocket.close(); //关闭被动模式
}
catch(Exception e) {}
try
{
if(this.tempSocket!=null) tempSocket.close(); //关闭空套接字
}
catch(Exception e) {}
try
{
if(this.socket!=null) socket.close(); //关闭当前套接字
}
catch(Exception e) {}
}
System.out.println(clientIP + " 断开连接......");
}
private void response(String s) throws Exception //自定义:向客户发送消息
{
// System.out.println(" [RESPONSE] "+s);
writer.write(s);
writer.newLine();
writer.flush(); // 注意要flush否则响应仍在缓冲区
}
private static String pad(int length) //自定义:生成一个空字符串
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < length; i++)
buf.append((char)' ');
return buf.toString();//转换为String
}
private String getParam(String cmd, String start) //自定义:获取参数
{
String s = cmd.substring(start.length(), cmd.length());
return s.trim();
}
private String translatePath(String path) //自定义:获取路径
{
if(path==null) return root;
if(path.equals("")) return root;//为空,返回主目录
path = path.replace('/', '\\');//替换
return root + path;
}
// 获取文件长度,注意是一个字符串,并定义为标准的12个字符
private String getFileLength(long length)
{
String s = Long.toString(length);
int spaces = 12 - s.length();
for(int i=0; i<spaces; i++)
s = " " + s;
return s;
}
//接下来便是处理用户命令,这个方法有点长,需要重构一下,我只是把LIST命令单独挪了出来:
private void parseCommand(String s) throws Exception
{
if(s==null || s.equals(""))
return;
if(s.startsWith("USER ")) {
response("331 请输入密码");
}
else if(s.startsWith("PASS ")) {
response("230 欢迎您的到来!");
}
else if(s.equals("QUIT")) {
response("221 欢迎再来!");
}
else if(s.equals("TYPE A")) {
response("200 TYPE set to A.");
}
else if(s.equals("TYPE I")) {
response("200 TYPE set to I.");
}
else if(s.equals("NOOP")) {
response("200 NOOP OK.");
}
else if(s.startsWith("CWD")) { // 设置当前目录,注意没有检查目录是否有效
this.currentDir = getParam(s, "CWD ");//取CWD后的字符,即当前目录
response("250 CWD 命令执行成功.");
}
else if(s.startsWith("CDUP")) {
int n = this.currentDir.lastIndexOf("/");
this.currentDir = this.currentDir.substring(0,n);
response("250 CWD command succesful");
}
else if(s.equals("PWD")) { // 打印当前目录
response("257 \"" + this.currentDir + "\" 是当前目录.");
}
/*??*/ else if(s.startsWith("PORT ")) {
// 记录端口
String[] params = getParam(s, "PORT ").split(",");
if(params.length<=4 || params.length>=7)//限定端口号为4至7位
response("500 command param error.");
else {
this.host = params[0] + "." + params[1] + "." + params[2] + "." + params[3];//客户端IP
String port1 = null;
String port2 = null;
if(params.length == 6) {//???????
port1 = params[4];
port2 = params[5];
}
else {
port1 = "0";
port2 = params[4];
}
this.port = Integer.parseInt(port1) * 256 + Integer.parseInt(port2);
response("200 command successful.");
}
}
else if(s.equals("PASV")) { // 进入被动模式
if(pasvSocket!=null)
pasvSocket.close();
try {
pasvSocket = new ServerSocket(0);
int pPort = pasvSocket.getLocalPort();
String s_port;
if(pPort<=255)
s_port = "255";
else {
int p1 = pPort / 256;
int p2 = pPort - p1*256;
s_port = p1 + "," + p2;
}
pasvSocket.setSoTimeout(60000);
response("227 Entering Passive Mode ("
+ InetAddress.getLocalHost().getHostAddress().replace('.', ',')
+ "," + s_port + ")");
}
catch(Exception e) {
if(pasvSocket!=null) {
pasvSocket.close();
pasvSocket = null;
}
}
}
else if(s.startsWith("RETR")) { // 下载文件
String file = currentDir + (currentDir.endsWith("/") ? "" : "/") + getParam(s, "RETR");
System.out.println("download file: " + file);
Socket dataSocket;
// 根据上一次的PASV或PORT命令决定使用哪个socket
if(pasvSocket!=null)
dataSocket = pasvSocket.accept();
else
dataSocket = new Socket(this.host, this.port);
OutputStream dos = null;
InputStream fis = null;
response("150 Opening ASCII mode data connection.");
try {
fis = new BufferedInputStream(new FileInputStream(translatePath(file)));
dos = new DataOutputStream(new BufferedOutputStream(dataSocket.getOutputStream()));
// 开始正式发送数据:
byte[] buffer = new byte[20480]; // 发送缓冲 20k
int num = 0; // 发送一次读取的字节数
do {
num = fis.read(buffer);
if(num!=(-1)) {
// 发送:
dos.write(buffer, 0, num);
dos.flush();
}
} while(num!=(-1));
fis.close();
fis = null;
dos.close();
dos = null;
dataSocket.close();
dataSocket = null;
response("226 transfer complete."); // 响应一个成功标志
}
catch(Exception e) {
response("550 ERROR: File not found or access denied.");
}
finally {
try {
if(fis!=null) fis.close();
if(dos!=null) dos.close();
if(dataSocket!=null) dataSocket.close();
}
catch(Exception e) {}
}
}
//
else if(s.startsWith("STOR")) { // 上传文件
String file = currentDir + (currentDir.endsWith("/") ? "" : "/") + getParam(s, "RETR");
System.out.println("download file: " + file);
Socket dataSocket;
// 根据上一次的PASV或PORT命令决定使用哪个socket
if(pasvSocket!=null)
dataSocket = pasvSocket.accept();
else
dataSocket = new Socket(this.host, this.port);
OutputStream fis = null;
InputStream dos = null;
response("150 Opening ASCII mode data connection.");
try {
fis = new BufferedOutputStream(new FileOutputStream(translatePath(file)));
dos = new DataInputStream(new BufferedInputStream(dataSocket.getInputStream()));
// 开始正式发送数据:
byte[] buffer = new byte[20480]; // 发送缓冲 20k
int num = 0; // 发送一次读取的字节数
while((num = dos.read(buffer,0,1024))!=-1)
{
fis.write(buffer,0,num);
fis.flush();
}//上传到服务器
fis.close();
fis = null;
dos.close();
dos = null;
dataSocket.close();
dataSocket = null;
response("226 transfer complete."); // 响应一个成功标志
}
catch(Exception e) {
response("550 ERROR: File not found or access denied.");
}
finally {
try {
if(fis!=null) fis.close();
if(dos!=null) dos.close();
if(dataSocket!=null) dataSocket.close();
}
catch(Exception e) {}
}
}
else if(s.equals("LIST")) { // 列当前目录文件
Socket dataSocket;
// 根据上一次的PASV或PORT命令决定使用哪个socket
if(pasvSocket!=null)
dataSocket = pasvSocket.accept();
else
dataSocket = new Socket(this.host, this.port);
PrintWriter writer = new PrintWriter(new BufferedOutputStream(dataSocket.getOutputStream()));
response("150 Opening ASCII mode data connection.");
try {
responseList(writer, this.currentDir);
writer.close();
dataSocket.close();
response("226 transfer complete.");
}
catch(IOException e) {
writer.close();
dataSocket.close();
response(e.getMessage());
}
dataSocket = null;
}
else {
response("500 invalid command"); // 没有匹配的命令,输出错误信息
}
}
// 响应LIST命令
private void responseList(PrintWriter writer, String path) throws IOException {
File dir = new File(translatePath(path));
if(!dir.isDirectory())
throw new IOException("550 No such file or directory");
File[] files = dir.listFiles();
String dateStr;
for(int i=0; i<files.length; i++) {
dateStr = new SimpleDateFormat("MMM dd hh:mm").format(new Date(files[i].lastModified()));
if(files[i].isDirectory()) {
writer.println("drwxrwxrwx 1 ftp System 0 "
+ dateStr + " " + files[i].getName());
}
else {
writer.println("-rwxrwxrwx 1 ftp System "
+ getFileLength(files[i].length()) + " " + dateStr + " " + files[i].getName());
}
}
String file_header = "-rwxrwxrwx 1 ftp System 0 Aug 5 19:59 ";
String dir_header = "drwxrwxrwx 1 ftp System 0 Aug 15 19:59 ";
writer.println("total " + files.length);
writer.flush();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -