Java implementation of FTP server function instance code
- 2020-04-01 04:29:52
- OfStack
FTP(File Transfer Protocol) is a Protocol used to Transfer files over the Internet. You can Upload or Download files on the Internet via an FTP server. FTP is the real-time online service, before using it must be with the service of a user (user name and password), work the client have to login to the server side of the machine, after the user login to file search and file transfer and related operations, such as changing the current working directory, file directory, set the transmission parameters and file transfer, etc. FTP can be used to transfer all types of files, such as text files, binary executable files, image files, sound files, and data compression files.
The FTP command
The main operations of FTP are based on various commands. Common commands are:
Set the transfer mode, it include ASC Ⅱ (text) and BINARY BINARY mode;
Directory operation to change or display the current directory of the remote computer (CD, dir/ls command);
Connection operation. The open command is used to establish a connection to the remote computer. The close command is used to close the connection;
The send operation, the put command is used to transfer files to a remote computer. The mput command is used to transfer multiple files to a remote computer.
The get command is used to receive a file. The mget command is used to receive multiple files.
import java.net.Socket;
import org.apache.log4j.Logger;
public class ServerA{
public static void main(String[] args){
final String F_DIR = "c:/test";//Root path
final int PORT = 22;//Monitor 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 requests
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;
public class ClientThread extends Thread {
private Socket socketClient;//The client socket
private Logger logger;//The log object
private String dir;//An absolute path
private String pdir = "/";//Relative paths
private final static Random generator = new Random();//The 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";//The user name
String password = "";//password
String command = "";//The command
boolean loginStuts = false;//The 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 received file
Socket tempsocket = null;
//Print 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 {
// Gets input from the user The command
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;
}
// USERThe 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);
}
loginStuts = false;
} //end USER
// PASSThe 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+" by "+username+" user login ");
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
// PWDThe 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
// CWDThe command
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{
//Determine if the directory exists
String tmpDir = dir + "/" + str;
File file = new File(tmpDir);
if(file.exists()){//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{//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
// QUITThe 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
//PORT command, transmit data in active 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 sockets in active mode
tempsocket = 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, transfer data in passive mode
else if(command.toUpperCase().startsWith("PASV")) {
logger.info("("+username+") ("+clientIp+")> "+command);
if(loginStuts){
ServerSocket ss = null;
while( true ){
//Gets the server's free port
port_high = 1 + generator.nextInt(20);
port_low = 100 + generator.nextInt(1000);
try {
//Server bound port
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 in passive mode
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
//RETRThe 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 {
//Creates a stream of randomly accessed files with the specified name that are read from and optionally written to
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 (" 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
//STORThe 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
//NLSTThe 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[] 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 (" 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
//LISTThe 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 the 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 illegal The 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;
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
### 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
## The output DEBUG Logs above level
log4j.appender.D=org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File=c:/logs/logs.log
log4j.appender.D.Append =true
## The output DEBUG Logs above level
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 the 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 the output ERROR Logs above 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%n
The above content is this site to introduce the Java implementation of FTP server function instance code of the relevant knowledge, I hope you like.