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服务器功能实例代码的相关知识,希望大家喜欢。