⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpserver.java

📁 Java实现的explorer程序
💻 JAVA
字号:
/*
 * FtpClient.java
 *
 * Created on 2007年8月8日, 上午10:09
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package explorer;

import java.net.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
import javax.swing.filechooser.*;

/**
 *
 * @author king
 */

public class FtpServer extends Thread {
    public static final int FTP_PORT = 21; // default port
    ServerSocket ftpsocket = null;

    public static void createServer() {
        if (FtpConnection.root == null)
            FtpConnection.root = "D:\\Study";
        System.out.println("[info] ftp server root: " + FtpConnection.root);
        new FtpServer().start();
    }

    public void run() {
        Socket client = null;
        try {
            ftpsocket = new ServerSocket(FTP_PORT);
            System.out.println("[info] listening port: " + FTP_PORT);
            for(;;) {
                client = ftpsocket.accept();
                new FtpConnection(client).start();
            }
        }
        catch(Exception e) { e.printStackTrace(); }
    }
}

class FtpConnection extends Thread {
    /** 主目录 */
    static public String root = null;
    private String currentDir = "/"; // 当前目录
    private String parentDir = "";
    private Socket socket;
    private BufferedReader reader = null;
    private BufferedWriter writer = null;
    private String clientIP = null;
    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();
    }

    public void run() {
        String command;
        try {
            System.out.println(clientIP + " connected.");
            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("command from " + 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 + " disconnected.");
    }
    
    private void response(String s) throws Exception {
        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();
    }

    // 获取参数
    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;
    }

    // 获取文件长度,注意是一个字符串
    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;
    }
    
    private void parseCommand(String s) throws Exception {
        if(s==null || s.equals(""))
            return;
    	if(s.startsWith("USER ")) {
            response("331 need password");
        }
    	else if(s.startsWith("PASS ")) {
            response("230 welcome to my ftp!");
    	}
    	else if(s.equals("QUIT")) {
            response("221 欢迎再来!");
    	}
        else if(s.startsWith("CWD ")) { // 设置当前目录,注意没有检查目录是否有效
            this.parentDir = this.currentDir;
            this.currentDir += getParam(s, "CWD ");
            this.currentDir += '\\';
            response("250 CWD command successful.");
    	}
        else if(s.equals("CWD..")) {
            this.currentDir = this.parentDir;
            int pos = this.parentDir.lastIndexOf('\\',this.parentDir.length()-2);
            this.parentDir = this.parentDir.substring(0,pos+1);
            System.out.println(this.parentDir + "   " +this.currentDir);
            response("250 CWD.. command successful");
        }
        else if(s.equals("PWD")) { // 打印当前目录
            response("257 \"" + this.currentDir + "\" is current directory.");
    	}
    	else if(s.startsWith("PORT ")) {
            // 记录端口
            String[] params = getParam(s, "PORT ").split(",");
            if(params.length<=4 || params.length>=7)
            response("500 command param error.");
            else 
            {
                this.host = params[0] + "." + params[1] + "." + params[2] + "." + params[3];
            	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.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 = 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(new Filter());
    	String dateStr;
        String fileStyle;
        for(int i=0; i<files.length; i++) {
            dateStr = new Date(files[i].lastModified()).toString();
            fileStyle = FileSystemView.getFileSystemView().getSystemTypeDescription(files[i]);
            if(files[i].isDirectory()) {
                writer.println(files[i].getName() + ";" + 0 + ";" + fileStyle + ";" + dateStr);
            }
            else {
                writer.println(files[i].getName() + ";" + getFileLength(files[i].length()) + ";" + fileStyle + ";" + dateStr);
            }
        }
        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();
    }
}

class Filter implements java.io.FileFilter{
    public boolean accept(File pathname){
        return ((!pathname.getName().endsWith(".sys"))&&(!FileSystemView.getFileSystemView().isHiddenFile(pathname)));
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -