Java实现FTP服务器功能实例代码
FTP(FileTransferProtocol文件传输协议)是Internet上用来传送文件的协议。在Internet上通过FTP服务器可以进行文件的上传(Upload)或下载(Download)。FTP是实时联机服务,在使用它之前必须是具有该服务的一个用户(用户名和口令),工作时客户端必须先登录到作为服务器一方的计算机上,用户登录后可以进行文件搜索和文件传送等有关操作,如改变当前工作目录、列文件目录、设置传输参数及传送文件等。使用FTP可以传送所有类型的文件,如文本文件、二进制可执行文件、图象文件、声音文件和数据压缩文件等。
FTP命令
FTP的主要操作都是基于各种命令基础之上的。常用的命令有:
设置传输模式,它包括ASCⅡ(文本)和BINARY二进制模式;
目录操作,改变或显示远程计算机的当前目录(cd、dir/ls命令);
连接操作,open命令用于建立同远程计算机的连接;close命令用于关闭连接;
发送操作,put命令用于传送文件到远程计算机;mput命令用于传送多个文件到远程计算机;
获取操作,get命令用于接收一个文件;mget命令用于接收多个文件。
importjava.net.Socket; importorg.apache.log4j.Logger; /** *角色——服务器A *@authorLeon * */ publicclassServerA{ publicstaticvoidmain(String[]args){ finalStringF_DIR="c:/test";//根路径 finalintPORT=22;//监听端口号 Logger.getRootLogger(); Loggerlogger=Logger.getLogger("com"); try{ ServerSockets=newServerSocket(PORT); logger.info("ConnectingtoserverA..."); logger.info("ConnectedSuccessful!LocalPort:"+s.getLocalPort()+".DefaultDirectory:'"+F_DIR+"'."); while(true){ //接受客户端请求 Socketclient=s.accept(); //创建服务线程 newClientThread(client,F_DIR).start(); } }catch(Exceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } } importjava.io.BufferedReader; importjava.io.File; importjava.io.FileNotFoundException; importjava.io.IOException; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.io.OutputStream; importjava.io.PrintWriter; importjava.io.RandomAccessFile; importjava.net.ConnectException; importjava.net.InetAddress; importjava.net.ServerSocket; importjava.net.Socket; importjava.net.UnknownHostException; importjava.nio.charset.Charset; importjava.util.Random; importorg.apache.log4j.Logger; /** *客户端子线程类 *@authorLeon * */ publicclassClientThreadextendsThread{ privateSocketsocketClient;//客户端socket privateLoggerlogger;//日志对象 privateStringdir;//绝对路径 privateStringpdir="/";//相对路径 privatefinalstaticRandomgenerator=newRandom();//随机数 publicClientThread(Socketclient,StringF_DIR){ this.socketClient=client; this.dir=F_DIR; } @Override publicvoidrun(){ Logger.getRootLogger(); logger=Logger.getLogger("com"); InputStreamis=null; OutputStreamos=null; try{ is=socketClient.getInputStream(); os=socketClient.getOutputStream(); }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } BufferedReaderbr=newBufferedReader(newInputStreamReader(is, Charset.forName("UTF-8"))); PrintWriterpw=newPrintWriter(os); StringclientIp=socketClient.getInetAddress().toString().substring(1);//记录客户端IP Stringusername="notloggedin";//用户名 Stringpassword="";//口令 Stringcommand="";//命令 booleanloginStuts=false;//登录状态 finalStringLOGIN_WARNING="530PleaseloginwithUSERandPASSfirst."; Stringstr="";//命令内容字符串 intport_high=0; intport_low=0; Stringretr_ip="";//接收文件的IP地址 Sockettempsocket=null; //打印欢迎信息 pw.println("220-FTPServerAversion1.0writtenbyLeonGuo"); pw.flush(); logger.info("("+username+")("+clientIp+")>Connected,sendingwelcomemessage..."); logger.info("("+username+")("+clientIp+")>220-FTPServerAversion1.0writtenbyLeonGuo"); booleanb=true; while(b){ try{ //获取用户输入的命令 command=br.readLine(); if(null==command)break; }catch(IOExceptione){ pw.println("331Failedtogetcommand"); pw.flush(); logger.info("("+username+")("+clientIp+")>331Failedtogetcommand"); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } b=false; } /* *访问控制命令 */ //USER命令 if(command.toUpperCase().startsWith("USER")){ logger.info("(notloggedin)("+clientIp+")>"+command); username=command.substring(4).trim(); if("".equals(username)){ pw.println("501Syntaxerror"); pw.flush(); logger.info("(notloggedin)("+clientIp+")>501Syntaxerror"); username="notloggedin"; } else{ pw.println("331Passwordrequiredfor"+username); pw.flush(); logger.info("(notloggedin)("+clientIp+")>331Passwordrequiredfor"+username); } loginStuts=false; }//endUSER //PASS命令 elseif(command.toUpperCase().startsWith("PASS")){ logger.info("(notloggedin)("+clientIp+")>"+command); password=command.substring(4).trim(); if(username.equals("root")&&password.equals("root")){ pw.println("230Loggedon"); pw.flush(); logger.info("("+username+")("+clientIp+")>230Loggedon"); //logger.info("客户端"+clientIp+"通过"+username+"用户登录"); loginStuts=true; } else{ pw.println("530Loginorpasswordincorrect!"); pw.flush(); logger.info("(notloggedin)("+clientIp+")>530Loginorpasswordincorrect!"); username="notloggedin"; } }//endPASS //PWD命令 elseif(command.toUpperCase().startsWith("PWD")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ //logger.info("用户"+clientIp+":"+username+"执行PWD命令"); pw.println("257/""+pdir+"/"iscurrentdirectory"); pw.flush(); logger.info("("+username+")("+clientIp+")>257/""+pdir+"/"iscurrentdirectory"); } else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endPWD //CWD命令 elseif(command.toUpperCase().startsWith("CWD")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ str=command.substring(3).trim(); if("".equals(str)){ pw.println("250Brokenclientdetected,missingargumenttoCWD./""+pdir+"/"iscurrentdirectory."); pw.flush(); logger.info("("+username+")("+clientIp+")>250Brokenclientdetected,missingargumenttoCWD./""+pdir+"/"iscurrentdirectory."); } else{ //判断目录是否存在 StringtmpDir=dir+"/"+str; Filefile=newFile(tmpDir); if(file.exists()){//目录存在 dir=dir+"/"+str; if("/".equals(pdir)){ pdir=pdir+str; } else{ pdir=pdir+"/"+str; } //logger.info("用户"+clientIp+":"+username+"执行CWD命令"); pw.println("250CWDsuccessful./""+pdir+"/"iscurrentdirectory"); pw.flush(); logger.info("("+username+")("+clientIp+")>250CWDsuccessful./""+pdir+"/"iscurrentdirectory"); } else{//目录不存在 pw.println("550CWDfailed./""+pdir+"/":directorynotfound."); pw.flush(); logger.info("("+username+")("+clientIp+")>550CWDfailed./""+pdir+"/":directorynotfound."); } } } else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endCWD //QUIT命令 elseif(command.toUpperCase().startsWith("QUIT")){ logger.info("("+username+")("+clientIp+")>"+command); b=false; pw.println("221Goodbye"); pw.flush(); logger.info("("+username+")("+clientIp+")>221Goodbye"); try{ Thread.currentThread(); Thread.sleep(1000); }catch(InterruptedExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } }//endQUIT /* *传输参数命令 */ //PORT命令,主动模式传输数据 elseif(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)); Stringstr1=str.substring(0,str.substring(0,str.lastIndexOf(",")).lastIndexOf(",")); retr_ip=str1.replace(",","."); try{ //实例化主动模式下的socket tempsocket=newSocket(retr_ip,port_high*256+port_low); //logger.info("用户"+clientIp+":"+username+"执行PORT命令"); pw.println("200portcommandsuccessful"); pw.flush(); logger.info("("+username+")("+clientIp+")>200portcommandsuccessful"); }catch(ConnectExceptionce){ pw.println("425Can'topendataconnection."); pw.flush(); logger.info("("+username+")("+clientIp+")>425Can'topendataconnection."); logger.error(ce.getMessage()); for(StackTraceElementste:ce.getStackTrace()){ logger.error(ste.toString()); } }catch(UnknownHostExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } }catch(NumberFormatExceptione){ pw.println("503Badsequenceofcommands."); pw.flush(); logger.info("("+username+")("+clientIp+")>503Badsequenceofcommands."); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endPORT //PASV命令,被动模式传输数据 elseif(command.toUpperCase().startsWith("PASV")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ ServerSocketss=null; while(true){ //获取服务器空闲端口 port_high=1+generator.nextInt(20); port_low=100+generator.nextInt(1000); try{ //服务器绑定端口 ss=newServerSocket(port_high*256+port_low); break; }catch(IOExceptione){ continue; } } //logger.info("用户"+clientIp+":"+username+"执行PASV命令"); InetAddressi=null; try{ i=InetAddress.getLocalHost(); }catch(UnknownHostExceptione1){ e1.printStackTrace(); } pw.println("227EnteringPassiveMode("+i.getHostAddress().replace(".",",")+","+port_high+","+port_low+")"); pw.flush(); logger.info("("+username+")("+clientIp+")>227EnteringPassiveMode("+i.getHostAddress().replace(".",",")+","+port_high+","+port_low+")"); try{ //被动模式下的socket tempsocket=ss.accept(); ss.close(); }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endPASV //RETR命令 elseif(command.toUpperCase().startsWith("RETR")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ str=command.substring(4).trim(); if("".equals(str)){ pw.println("501Syntaxerror"); pw.flush(); logger.info("("+username+")("+clientIp+")>501Syntaxerror"); } else{ try{ pw.println("150Openingdatachannelforfiletransfer."); pw.flush(); logger.info("("+username+")("+clientIp+")>150Openingdatachannelforfiletransfer."); RandomAccessFileoutfile=null; OutputStreamoutsocket=null; try{ //创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称 outfile=newRandomAccessFile(dir+"/"+str,"r"); outsocket=tempsocket.getOutputStream(); }catch(FileNotFoundExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } bytebytebuffer[]=newbyte[1024]; intlength; try{ while((length=outfile.read(bytebuffer))!=-1){ outsocket.write(bytebuffer,0,length); } outsocket.close(); outfile.close(); tempsocket.close(); } catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } //logger.info("用户"+clientIp+":"+username+"执行RETR命令"); pw.println("226TransferOK"); pw.flush(); logger.info("("+username+")("+clientIp+")>226TransferOK"); }catch(Exceptione){ pw.println("503Badsequenceofcommands."); pw.flush(); logger.info("("+username+")("+clientIp+")>503Badsequenceofcommands."); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } } else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endRETR //STOR命令 elseif(command.toUpperCase().startsWith("STOR")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ str=command.substring(4).trim(); if("".equals(str)){ pw.println("501Syntaxerror"); pw.flush(); logger.info("("+username+")("+clientIp+")>501Syntaxerror"); } else{ try{ pw.println("150Openingdatachannelforfiletransfer."); pw.flush(); logger.info("("+username+")("+clientIp+")>150Openingdatachannelforfiletransfer."); RandomAccessFileinfile=null; InputStreaminsocket=null; try{ infile=newRandomAccessFile(dir+"/"+str,"rw"); insocket=tempsocket.getInputStream(); }catch(FileNotFoundExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } bytebytebuffer[]=newbyte[1024]; intlength; try{ while((length=insocket.read(bytebuffer))!=-1){ infile.write(bytebuffer,0,length); } insocket.close(); infile.close(); tempsocket.close(); } catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } //logger.info("用户"+clientIp+":"+username+"执行STOR命令"); pw.println("226TransferOK"); pw.flush(); logger.info("("+username+")("+clientIp+")>226TransferOK"); }catch(Exceptione){ pw.println("503Badsequenceofcommands."); pw.flush(); logger.info("("+username+")("+clientIp+")>503Badsequenceofcommands."); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } }else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endSTOR //NLST命令 elseif(command.toUpperCase().startsWith("NLST")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ try{ pw.println("150Openingdatachannelfordirectorylist."); pw.flush(); logger.info("("+username+")("+clientIp+")>150Openingdatachannelfordirectorylist."); PrintWriterpwr=null; try{ pwr=newPrintWriter(tempsocket.getOutputStream(),true); }catch(IOExceptione1){ e1.printStackTrace(); } Filefile=newFile(dir); String[]dirstructure=newString[10]; dirstructure=file.list(); for(inti=0;i<dirstructure.length;i++){ pwr.println(dirstructure[i]); } try{ tempsocket.close(); pwr.close(); }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } //logger.info("用户"+clientIp+":"+username+"执行NLST命令"); pw.println("226TransferOK"); pw.flush(); logger.info("("+username+")("+clientIp+")>226TransferOK"); }catch(Exceptione){ pw.println("503Badsequenceofcommands."); pw.flush(); logger.info("("+username+")("+clientIp+")>503Badsequenceofcommands."); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } }else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endNLST //LIST命令 elseif(command.toUpperCase().startsWith("LIST")){ logger.info("("+username+")("+clientIp+")>"+command); if(loginStuts){ try{ pw.println("150Openingdatachannelfordirectorylist."); pw.flush(); logger.info("("+username+")("+clientIp+")>150Openingdatachannelfordirectorylist."); PrintWriterpwr=null; try{ pwr=newPrintWriter(tempsocket.getOutputStream(),true); }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } FtpUtil.getDetailList(pwr,dir); try{ tempsocket.close(); pwr.close(); }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } //logger.info("用户"+clientIp+":"+username+"执行LIST命令"); pw.println("226TransferOK"); pw.flush(); logger.info("("+username+")("+clientIp+")>226TransferOK"); }catch(Exceptione){ pw.println("503Badsequenceofcommands."); pw.flush(); logger.info("("+username+")("+clientIp+")>503Badsequenceofcommands."); logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } }else{ pw.println(LOGIN_WARNING); pw.flush(); logger.info("("+username+")("+clientIp+")>"+LOGIN_WARNING); } }//endLIST //输入非法命令 else{ logger.info("("+username+")("+clientIp+")>"+command); pw.println("500Syntaxerror,commandunrecognized."); pw.flush(); logger.info("("+username+")("+clientIp+")>500Syntaxerror,commandunrecognized."); } }//endwhile try{ logger.info("("+username+")("+clientIp+")>disconnected."); //logger.info("用户"+clientIp+":"+username+"退出"); br.close(); socketClient.close(); pw.close(); if(null!=tempsocket){ tempsocket.close(); } }catch(IOExceptione){ logger.error(e.getMessage()); for(StackTraceElementste:e.getStackTrace()){ logger.error(ste.toString()); } } } } importjava.io.File; importjava.io.PrintWriter; importjava.text.SimpleDateFormat; importjava.util.Date; /** *FTP工具类 *@authorLeon * */ publicclassFtpUtil{ publicstaticvoidgetDetailList(PrintWriterpw,Stringpath){ Filedir=newFile(path); if(!dir.isDirectory()){ pw.println("500Nosuchfileordirectory./r/n"); } File[]files=dir.listFiles(); StringmodifyDate; for(inti=0;i<files.length;i++){ modifyDate=newSimpleDateFormat("yyyy/MM/ddhh:mm:ss") .format(newDate(files[i].lastModified())); if(files[i].isDirectory()){ pw.println("drwxr-xr-xftpftp0" +modifyDate+""+files[i].getName()); }else{ pw.println("-rw-r-r--1ftpftp" +files[i].length()+""+modifyDate+"" +files[i].getName()); } pw.flush(); } pw.println("total:"+files.length); } } ###setloglevels### 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-ddHH: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-ddHH:mm:ss}[%t:%r]-[%p]%m%n
以上内容是小编给大家介绍的Java实现FTP服务器功能实例代码的相关知识,希望大家喜欢。