FTP (File Transfer Protocol file transfer protocol) is a protocol used to transfer files on the Internet. Files can be uploaded (uploaded) or downloaded (Download) through the FTP server on the Internet. FTP is a real-time online service. Before using it, it must be a user (user name and password) with the service. When working, the client must first log in to the computer that is the server. After logging in, the user can perform file search and file transfer and other related operations, such as changing the current working directory, column file directory, setting transmission parameters and transfer files, etc. Use FTP to transfer all types of files, such as text files, binary executable files, image files, sound files, and data compression files.
FTP Commands
The main operations of FTP are based on various commands. Commonly used commands are:
Sets the transmission mode, which includes ASCⅡ (text) and BINARY binary mode;
Directory operation, changing or displaying the current directory of the remote computer (cd, dir/ls command);
Connection operation, the open command is used to establish a connection with a remote computer; the close command is used to close the connection;
Send operation, the put command is used to transfer files to a remote computer; the put command is used to transfer multiple files to a remote computer;
Get operation, get command is used to receive one file; mgget command is used to receive multiple files.
import java.net.Socket; import org.apache.log4j.Logger; /** * Role - Server A * @author Leon * */ public class ServerA{ public static void main(String[] args){ final String F_DIR = "c:/test";//root path final int PORT = 22;//listen port number 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 ){ //Accept client request Socket client = s.accept(); //Create a service thread 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; /** * Client subthread class* @author Leon * */ public class ClientThread extends Thread { private Socket socketClient;//Client socket private Logger logger;//Login object private String dir;//Absolute path private String pdir = "/";//Relative path private final static Random generator = new Random();//Random number 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);//Record client IP String username = "not logged in";//Username String password = "";//Password String command = "";//Command boolean loginStus = false;//Login status final String LOGIN_WARNING = "530 Please log in with USER and PASS first."; String str = "";//Command content string int port_high = 0; int port_low = 0; String retr_ip = "";//The IP address of the receiving file Socket tempsocket = null; //Print the welcome message 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 { //Get the command entered by the user 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; } /* * Access control command*/ // USER command 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); } loginStus = false; } //end USER // PASS command 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("Client"+clientIp+""User login"); loginStus = 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 command else if(command.toUpperCase().startsWith("PWD")){ logger.info("("+username+") ("+clientIp+")> "+command); if(loginStuts){ // logger.info("User"+clientIp+": "+username+"Execute PWD command"); 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 command else if(command.toUpperCase().startsWith("CWD")){ logger.info("("+username+") ("+clientIp+")> "+command); if(loginStus){ 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{ //Judge whether the directory has String tmpDir = dir + "/" + str; File file = new File(tmpDir); if(file.exists()){//Dir directory exists dir = dir + "/" + str; if("/".equals(pdir)){ pdir = pdir + str; } else{ pdir = pdir + "/" + str; } // logger.info("user"+clientIp+": "+username+"Execute CWD command"); pw.println("250 CWD successful. /"+pdir+"/" is current directory"); pw.flush(); logger.info("("+username+") ("+clientIp+")> 250 CWD successful. /"+pdir+"/" is current directory"); } else{//The directory does not exist 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 command 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 /* * Transfer parameter command*/ //PORT command, actively transmit data in mode 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 { //Instantiate socket tempsocket in active mode = new Socket(retr_ip,port_high * 256 + port_low); // logger.info("User"+clientIp+": "+username+"Execute PORT command"); 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 command, passive mode transfer data else if(command.toUpperCase().startsWith("PASV")) { logger.info("("+username+") ("+clientIp+")> "+command); if(loginStuts){ ServerSocket ss = null; while( true ){ //Get the server free port port_high = 1 + generator.nextInt(20); port_low = 100 + generator.nextInt(1000); try { //Server binding ports ss = new ServerSocket(port_high * 256 + port_low); break; } catch (IOException e) { continue; } } // logger.info("User"+clientIp+": "+username+"Execute PASV command"); 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 in passive mode = 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 command 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 { //Create a random access file stream from and write (optional) to it, with the specified name 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(); tempsocket.close(); } catch(IOException e){ logger.error(e.getMessage()); for(StackTraceElement ste : e.getStackTrace()){ logger.error(ste.toString()); } } // logger.info("User"+clientIp+": "+username+"Execute RETR command"); 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 command 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("User"+clientIp+": "+username+"Execute STOR command"); 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 command 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[] distructure = new String[10]; distructure= 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("User"+clientIp+": "+username+"Execute NLST command"); 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 command 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("User"+clientIp+": "+username+"Execute LIST command"); 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 // Enter the illegal command 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("user"+clientIp+": "+username+"exit"); 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 tool class* @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-rr--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 ### Output to console### 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 ## Output log4j.appender.D=org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File=c:/logs/logs.log log4j.appender.D.Append =true ## Output 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 ### Save exception information to a separate file### log4j.appender.E=org.apache.log4j.DailyRollingFileAppender ## Exception log file name log4j.appender.E.File=c:/logs/errors.log log4j.appender.E.Append=true ## Only output logs above the ERROR level!!! 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%nThe above content is the relevant knowledge about Java implementation of FTP server function example code introduced to you by the editor. I hope you like it.