Java实现FTP服务器功能实例代码
程序员文章站
2024-03-08 16:58:40
ftp(file transfer protocol 文件传输协议)是internet 上用来传送文件的协议。在internet上通过ftp 服务器可以进行文件的上传(up...
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服务器功能实例代码的相关知识,希望大家喜欢。
上一篇: asp.net 动态引用样式表代码