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

📄 ftpconnection.java

📁 实现ftp代理服务器的基本功能
💻 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 + -