首页 > 编程 > Java > 正文

Java实现FTP服务器功能实例代码

2019-11-26 14:44:50
字体:
来源:转载
供稿:网友

FTP(File Transfer Protocol 文件传输协议)是Internet 上用来传送文件的协议。在Internet上通过FTP 服务器可以进行文件的上传(Upload)或下载(Download)。FTP是实时联机服务,在使用它之前必须是具有该服务的一个用户(用户名和口令),工作时客户端必须先登录到作为服务器一方的计算机上,用户登录后可以进行文件搜索和文件传送等有关操作,如改变当前工作目录、列文件目录、设置传输参数及传送文件等。使用FTP可以传送所有类型的文件,如文本文件、二进制可执行文件、图象文件、声音文件和数据压缩文件等。

FTP 命令

  FTP 的主要操作都是基于各种命令基础之上的。常用的命令有:
   设置传输模式,它包括ASCⅡ(文本) 和BINARY 二进制模式;
   目录操作,改变或显示远程计算机的当前目录(cd、dir/ls 命令);
   连接操作,open命令用于建立同远程计算机的连接;close命令用于关闭连接;
   发送操作,put命令用于传送文件到远程计算机;mput 命令用于传送多个文件到远程计算机;
   获取操作,get命令用于接收一个文件;mget命令用于接收多个文件。

import java.net.Socket; import org.apache.log4j.Logger; /**  * 角色――服务器A  * @author Leon  *  */ public class ServerA{   public static void main(String[] args){     final String F_DIR = "c:/test";//根路径     final int PORT = 22;//监听端口号     Logger.getRootLogger();     Logger logger = Logger.getLogger("com");     try{       ServerSocket s = new ServerSocket(PORT);       logger.info("Connecting to server A...");       logger.info("Connected Successful! Local Port:"+s.getLocalPort()+". Default Directory:'"+F_DIR+"'.");       while( true ){         //接受客户端请求         Socket client = s.accept();         //创建服务线程         new ClientThread(client, F_DIR).start();       }     } catch(Exception e) {       logger.error(e.getMessage());       for(StackTraceElement ste : e.getStackTrace()){         logger.error(ste.toString());       }     }   } } import java.io.BufferedReader;  import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.net.ConnectException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.util.Random; import org.apache.log4j.Logger; /**  * 客户端子线程类  * @author Leon  *  */ public class ClientThread extends Thread {   private Socket socketClient;//客户端socket   private Logger logger;//日志对象   private String dir;//绝对路径   private String pdir = "/";//相对路径   private final static Random generator = new Random();//随机数   public ClientThread(Socket client, String F_DIR){     this.socketClient = client;     this.dir = F_DIR;   }   @Override   public void run() {     Logger.getRootLogger();     logger = Logger.getLogger("com");     InputStream is = null;     OutputStream os = null;     try {       is = socketClient.getInputStream();       os = socketClient.getOutputStream();     } catch (IOException e) {       logger.error(e.getMessage());       for(StackTraceElement ste : e.getStackTrace()){         logger.error(ste.toString());       }     }     BufferedReader br = new BufferedReader(new InputStreamReader(is,         Charset.forName("UTF-8")));     PrintWriter pw = new PrintWriter(os);     String clientIp = socketClient.getInetAddress().toString().substring(1);//记录客户端IP     String username = "not logged in";//用户名     String password = "";//口令     String command = "";//命令     boolean loginStuts = false;//登录状态     final String LOGIN_WARNING = "530 Please log in with USER and PASS first.";     String str = "";//命令内容字符串     int port_high = 0;     int port_low = 0;     String retr_ip = "";//接收文件的IP地址     Socket tempsocket = null;     //打印欢迎信息     pw.println("220-FTP Server A version 1.0 written by Leon Guo");     pw.flush();     logger.info("("+username+") ("+clientIp+")> Connected, sending welcome message...");     logger.info("("+username+") ("+clientIp+")> 220-FTP Server A version 1.0 written by Leon Guo");     boolean b = true;     while ( b ){       try {         //获取用户输入的命令         command = br.readLine();         if(null == command) break;       } catch (IOException e) {         pw.println("331 Failed to get command");         pw.flush();         logger.info("("+username+") ("+clientIp+")> 331 Failed to get command");         logger.error(e.getMessage());         for(StackTraceElement ste : e.getStackTrace()){           logger.error(ste.toString());         }         b = false;       }       /*        * 访问控制命令        */       // USER命令       if(command.toUpperCase().startsWith("USER")){         logger.info("(not logged in) ("+clientIp+")> "+command);         username = command.substring(4).trim();          if("".equals(username)){           pw.println("501 Syntax error");           pw.flush();           logger.info("(not logged in) ("+clientIp+")> 501 Syntax error");           username = "not logged in";         }         else{           pw.println("331 Password required for " + username);           pw.flush();           logger.info("(not logged in) ("+clientIp+")> 331 Password required for " + username);         }         loginStuts = false;       } //end USER       // PASS命令       else if(command.toUpperCase().startsWith("PASS")){         logger.info("(not logged in) ("+clientIp+")> "+command);         password = command.substring(4).trim();          if(username.equals("root") && password.equals("root")){           pw.println("230 Logged on");           pw.flush();           logger.info("("+username+") ("+clientIp+")> 230 Logged on"); //         logger.info("客户端 "+clientIp+" 通过 "+username+"用户登录");           loginStuts = true;         }         else{           pw.println("530 Login or password incorrect!");           pw.flush();           logger.info("(not logged in) ("+clientIp+")> 530 Login or password incorrect!");           username = "not logged in";         }       } //end PASS       // PWD命令       else if(command.toUpperCase().startsWith("PWD")){         logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){ //         logger.info("用户"+clientIp+":"+username+"执行PWD命令");           pw.println("257 /""+pdir+"/" is current directory");           pw.flush();           logger.info("("+username+") ("+clientIp+")> 257 /""+pdir+"/" is current directory");         }         else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end PWD       // CWD命令       else if(command.toUpperCase().startsWith("CWD")){         logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           str = command.substring(3).trim();           if("".equals(str)){             pw.println("250 Broken client detected, missing argument to CWD. /""+pdir+"/" is current directory.");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 250 Broken client detected, missing argument to CWD. /""+pdir+"/" is current directory.");           }           else{             //判断目录是否存在             String tmpDir = dir + "/" + str;             File file = new File(tmpDir);             if(file.exists()){//目录存在               dir = dir + "/" + str;               if("/".equals(pdir)){                 pdir = pdir + str;               }               else{                 pdir = pdir + "/" + str;               } //             logger.info("用户"+clientIp+":"+username+"执行CWD命令");               pw.println("250 CWD successful. /""+pdir+"/" is current directory");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 250 CWD successful. /""+pdir+"/" is current directory");             }             else{//目录不存在               pw.println("550 CWD failed. /""+pdir+"/": directory not found.");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 550 CWD failed. /""+pdir+"/": directory not found.");             }           }         }         else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end CWD       // QUIT命令       else if(command.toUpperCase().startsWith("QUIT")){         logger.info("("+username+") ("+clientIp+")> "+command);         b = false;         pw.println("221 Goodbye");         pw.flush();         logger.info("("+username+") ("+clientIp+")> 221 Goodbye");         try {           Thread.currentThread();           Thread.sleep(1000);         } catch (InterruptedException e) {           logger.error(e.getMessage());           for(StackTraceElement ste : e.getStackTrace()){             logger.error(ste.toString());           }         }       } //end QUIT       /*        * 传输参数命令        */       //PORT命令,主动模式传输数据       else if(command.toUpperCase().startsWith("PORT")){         logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           try {             str = command.substring(4).trim();             port_low = Integer.parseInt(str.substring(str.lastIndexOf(",")+1));             port_high = Integer.parseInt(str.substring(0, str.lastIndexOf(","))                 .substring(str.substring(0, str.lastIndexOf(",")).lastIndexOf(",")+1));             String str1 = str.substring(0, str.substring(0, str.lastIndexOf(",")).lastIndexOf(","));             retr_ip = str1.replace(",", ".");             try {               //实例化主动模式下的socket               tempsocket = new Socket(retr_ip,port_high * 256 + port_low); //             logger.info("用户"+clientIp+":"+username+"执行PORT命令");               pw.println("200 port command successful");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 200 port command successful");             } catch (ConnectException ce) {               pw.println("425 Can't open data connection.");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 425 Can't open data connection.");               logger.error(ce.getMessage());               for(StackTraceElement ste : ce.getStackTrace()){                 logger.error(ste.toString());               }             } catch (UnknownHostException e) {               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             } catch (IOException e) {               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }           } catch (NumberFormatException e) {             pw.println("503 Bad sequence of commands.");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 503 Bad sequence of commands.");             logger.error(e.getMessage());             for(StackTraceElement ste : e.getStackTrace()){               logger.error(ste.toString());             }           }         }         else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end PORT       //PASV命令,被动模式传输数据       else if(command.toUpperCase().startsWith("PASV")) {          logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           ServerSocket ss = null;           while( true ){             //获取服务器空闲端口             port_high = 1 + generator.nextInt(20);             port_low = 100 + generator.nextInt(1000);             try {               //服务器绑定端口               ss = new ServerSocket(port_high * 256 + port_low);               break;             } catch (IOException e) {               continue;             }           } //         logger.info("用户"+clientIp+":"+username+"执行PASV命令");           InetAddress i = null;           try {             i = InetAddress.getLocalHost();           } catch (UnknownHostException e1) {             e1.printStackTrace();           }           pw.println("227 Entering Passive Mode ("+i.getHostAddress().replace(".", ",")+","+port_high+","+port_low+")");           pw.flush();           logger.info("("+username+") ("+clientIp+")> 227 Entering Passive Mode ("+i.getHostAddress().replace(".", ",")+","+port_high+","+port_low+")");           try {             //被动模式下的socket             tempsocket = ss.accept();             ss.close();           } catch (IOException e) {             logger.error(e.getMessage());             for(StackTraceElement ste : e.getStackTrace()){               logger.error(ste.toString());             }           }         }         else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end PASV       //RETR命令       else if(command.toUpperCase().startsWith("RETR")){         logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           str = command.substring(4).trim();           if("".equals(str)){             pw.println("501 Syntax error");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 501 Syntax error");           }           else {             try {               pw.println("150 Opening data channel for file transfer.");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 150 Opening data channel for file transfer.");               RandomAccessFile outfile = null;               OutputStream outsocket = null;               try {                 //创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称                 outfile = new RandomAccessFile(dir+"/"+str,"r");                 outsocket = tempsocket.getOutputStream();                } catch (FileNotFoundException e) {                  logger.error(e.getMessage());                 for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               } catch (IOException e) {                 logger.error(e.getMessage());                 for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               }                byte bytebuffer[]= new byte[1024];                int length;                try{                  while((length = outfile.read(bytebuffer)) != -1){                    outsocket.write(bytebuffer, 0, length);                  }                  outsocket.close();                  outfile.close();                  tempsocket.close();                }                catch(IOException e){                 logger.error(e.getMessage());                 for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               } //             logger.info("用户"+clientIp+":"+username+"执行RETR命令");               pw.println("226 Transfer OK");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 226 Transfer OK");             } catch (Exception e){               pw.println("503 Bad sequence of commands.");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 503 Bad sequence of commands.");               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }           }         }         else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       }//end RETR       //STOR命令       else if(command.toUpperCase().startsWith("STOR")){          logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           str = command.substring(4).trim();           if("".equals(str)){             pw.println("501 Syntax error");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 501 Syntax error");           }           else {             try {               pw.println("150 Opening data channel for file transfer.");                pw.flush();               logger.info("("+username+") ("+clientIp+")> 150 Opening data channel for file transfer.");               RandomAccessFile infile = null;               InputStream insocket = null;               try {                 infile = new RandomAccessFile(dir+"/"+str,"rw");                 insocket = tempsocket.getInputStream();                } catch (FileNotFoundException e) {                  logger.error(e.getMessage());                  for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               } catch (IOException e) {                 logger.error(e.getMessage());                  for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               }                byte bytebuffer[] = new byte[1024];                int length;                try{                 while((length =insocket.read(bytebuffer) )!= -1){                    infile.write(bytebuffer, 0, length);                  }                 insocket.close();                  infile.close();                  tempsocket.close();                }                catch(IOException e){                 logger.error(e.getMessage());                 for(StackTraceElement ste : e.getStackTrace()){                   logger.error(ste.toString());                 }               } //             logger.info("用户"+clientIp+":"+username+"执行STOR命令");               pw.println("226 Transfer OK");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 226 Transfer OK");             } catch (Exception e){               pw.println("503 Bad sequence of commands.");               pw.flush();               logger.info("("+username+") ("+clientIp+")> 503 Bad sequence of commands.");               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }           }         } else {           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end STOR       //NLST命令       else if(command.toUpperCase().startsWith("NLST")) {          logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           try {             pw.println("150 Opening data channel for directory list.");              pw.flush();             logger.info("("+username+") ("+clientIp+")> 150 Opening data channel for directory list.");             PrintWriter pwr = null;             try {               pwr= new PrintWriter(tempsocket.getOutputStream(),true);             } catch (IOException e1) {               e1.printStackTrace();             }              File file = new File(dir);              String[] dirstructure = new String[10];              dirstructure= file.list();              for(int i=0;i<dirstructure.length;i++){               pwr.println(dirstructure[i]);              }             try {               tempsocket.close();               pwr.close();             } catch (IOException e) {               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }  //           logger.info("用户"+clientIp+":"+username+"执行NLST命令");             pw.println("226 Transfer OK");              pw.flush();             logger.info("("+username+") ("+clientIp+")> 226 Transfer OK");           } catch (Exception e){             pw.println("503 Bad sequence of commands.");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 503 Bad sequence of commands.");             logger.error(e.getMessage());             for(StackTraceElement ste : e.getStackTrace()){               logger.error(ste.toString());             }           }         }else{           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end NLST       //LIST命令       else if(command.toUpperCase().startsWith("LIST")) {          logger.info("("+username+") ("+clientIp+")> "+command);         if(loginStuts){           try{             pw.println("150 Opening data channel for directory list.");              pw.flush();             logger.info("("+username+") ("+clientIp+")> 150 Opening data channel for directory list.");             PrintWriter pwr = null;             try {               pwr= new PrintWriter(tempsocket.getOutputStream(),true);             } catch (IOException e) {               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }              FtpUtil.getDetailList(pwr, dir);             try {               tempsocket.close();               pwr.close();             } catch (IOException e) {               logger.error(e.getMessage());               for(StackTraceElement ste : e.getStackTrace()){                 logger.error(ste.toString());               }             }  //           logger.info("用户"+clientIp+":"+username+"执行LIST命令");             pw.println("226 Transfer OK");              pw.flush();             logger.info("("+username+") ("+clientIp+")> 226 Transfer OK");           } catch (Exception e){             pw.println("503 Bad sequence of commands.");             pw.flush();             logger.info("("+username+") ("+clientIp+")> 503 Bad sequence of commands.");             logger.error(e.getMessage());             for(StackTraceElement ste : e.getStackTrace()){               logger.error(ste.toString());             }           }         } else {           pw.println(LOGIN_WARNING);           pw.flush();           logger.info("("+username+") ("+clientIp+")> "+LOGIN_WARNING);         }       } //end LIST       // 输入非法命令       else{         logger.info("("+username+") ("+clientIp+")> "+command);         pw.println("500 Syntax error, command unrecognized.");         pw.flush();         logger.info("("+username+") ("+clientIp+")> 500 Syntax error, command unrecognized.");       }     } //end while     try {       logger.info("("+username+") ("+clientIp+")> disconnected."); //     logger.info("用户"+clientIp+":"+username+"退出");       br.close();       socketClient.close();       pw.close();       if(null != tempsocket){         tempsocket.close();       }     } catch (IOException e) {       logger.error(e.getMessage());       for(StackTraceElement ste : e.getStackTrace()){         logger.error(ste.toString());       }     }   } } import java.io.File;  import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; /**  * FTP工具类  * @author Leon  *  */ public class FtpUtil {   public static void getDetailList(PrintWriter pw, String path){     File dir = new File(path);     if (!dir.isDirectory()) {       pw.println("500 No such file or directory./r/n");     }     File[] files = dir.listFiles();     String modifyDate;     for (int i = 0; i < files.length; i++) {       modifyDate = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss")           .format(new Date(files[i].lastModified()));       if (files[i].isDirectory()) {         pw.println("drwxr-xr-x ftp   ftp      0 "             + modifyDate + " " + files[i].getName());       } else {         pw.println("-rw-r-r--1 ftp   ftp      "             + files[i].length() + " " + modifyDate + " "             + files[i].getName());       }       pw.flush();     }     pw.println("total:" + files.length);   } } ### set log levels ### log4j.logger.com =debug,stdout,D,E ### 输出到控制台 ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%n ## 输出DEBUG级别以上的日志 log4j.appender.D=org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File=c:/logs/logs.log log4j.appender.D.Append =true ## 输出DEBUG级别以上的日志 log4j.appender.D.Threshold=DEBUG log4j.appender.D.layout=org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 保存异常信息到单独文件 ### log4j.appender.E=org.apache.log4j.DailyRollingFileAppender ## 异常日志文件名 log4j.appender.E.File=c:/logs/errors.log log4j.appender.E.Append=true ## 只输出ERROR级别以上的日志!!! log4j.appender.E.Threshold=ERROR log4j.appender.E.layout=org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 

以上内容是小编给大家介绍的Java实现FTP服务器功能实例代码的相关知识,希望大家喜欢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表