FTP服务器端的实现

时间:2021-03-22 00:16:37

1.主程序

package server;

import java.net.ServerSocket;
import java.net.Socket;

public class FtpServer extends Thread{
public static final int FTP_PORT=21;//服务器默认端口21
ServerSocket ftpsocket=null;//服务器套接字


public static void main(String[] args){
FtpConnection.root="C:\\ftp\\";
System.out.println("[info] ftp server root: "+FtpConnection.root );
new FtpServer().start();//创建FtpServer主线程对象,并运行
}
public void run(){
Socket client=null;

try{
ftpsocket=new ServerSocket(FTP_PORT);
System.out.println("[info] listening port: "+FTP_PORT);
for(;;){
client=ftpsocket.accept();//监控端口FTP_PORT=21,返回客户端套接字
new FtpConnection(client).start();
}
}catch(Exception e){
e.printStackTrace();
}
}
}

2.命令处理程序

package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class FtpConnection {
public static String root=null;//当前服务器的根目录
private String currentDir="/";//当前服务器上的工作目录
private Socket socket;//套接字
private BufferedReader reader=null;//字符输入流
private BufferedWriter writer=null;//字符输出流
private String clientIP=null;//客户端IP地址
private String host=null;//客户端端口
private int port=-1;//客户端端口
String user;
public FtpConnection(Socket socket){//获得客户端套接字信息
this.socket=socket;//客户端通信套接字
this.clientIP=socket.getInetAddress().getHostAddress();//获取客户机主机IP地址
}
//run()方法运行线程,创建服务器与客户端通信的字符流
//获得用户命令,处理命令,当收到QUIT时,关闭连接,结束Ftp会话
public void run(){
String command;
System.out.println(clientIP+" connected.");
try {
socket.setSoTimeout(10000);//Ftp超时设定
//字符输入流,接收客户端字符信息流
reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//字符输出流,发送至客户端字符信息流
writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
response("220-欢迎消息...");
for(;;){
command=reader.readLine();//获取客户端命令
if(command==null)
break;
System.out.println("command from "+clientIP+":"+command);
parseCommand(command);
if(command.equals("QUIT"))
break;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try{
if(reader!=null)
reader.close();
}catch(Exception e){
System.out.println("[info] reader==null");
}
try{
if(writer!=null)
writer.close();
}catch(Exception e){
System.out.println("[info] writer==null");
}
try{
if(this.socket!=null)
socket.close();
}catch(Exception e){
System.out.println("[info] this.socket==null");
}
System.out.println(clientIP+"disconnected.");
}
}
//服务器发送响应信息
private void response(String s) throws Exception {
// TODO Auto-generated method stub
System.out.println("[服务器]应答:"+s);
writer.write(s);
writer.newLine();
writer.flush();
}
//获取命令行中,命令后面附带的信息
private String getParam(String st,String cmd){
String string=st.substring(cmd.length(), st.length());
return string.trim();
}
//用户命令处理
private void parseCommand(String s) throws Exception {
// TODO Auto-generated method stub
if(s==null||s.equals(""))
return;
if(s.startsWith("USER")){
user=s.substring(4);
user=user.trim();
response("311 need passwrd");
return;
}
if(s.equals("PASS")){
response("230 welcome to my ftp! User:"+user);
return;
}
if(s.equals("QUIT")){
response("221 good bye!");
return;
}
if(s.equals("TYPE A")){
response("200 TYPE set to A.");
return;
}
if(s.equals("TYPE I")){
response("200 TYPE set to I.");
return;
}
if(s.equals("NOOP")){
response("200 NOOP OK.");
return;
}
//改变工作目录到指定的目录,注意没有检查目录是否有效
if(s.startsWith("CWD")){
this.currentDir=getParam(s, "CWD ");
response("250 CWD command successful.");
return;
}
//打印当前目录
if(s.equals("PWD ")){
response("257 \""+this.currentDir+"\""+"is current directory");
}
//主动模式PORT(PORT)命令
if(s.startsWith("PORT ")){
String[] params=getParam(s,"PORT ").split(",");
if(params.length<=4 || params.length>=7)
response("500 command param error.");
else{
this.host=params[0]"."params[1]"."params[2]"."params[3];
String port1=null;
String port2=null;
if(params.length==6){
port1=params[4];
port2=params[5];
}
else{
port1="0";
port2=params[4];
}
this.port=Integer.parseInt(port1)*256+Integer.parseInt(port2);
response("200 command successful.");
}
}
//被动模式PASV(PASSIVE)命令
ServerSocket pasvSocket=new ServerSocket();
Socket dataSocket;

if(s.equals("PASV ")){
if(pasvSocket!=null){
pasvSocket.close();
}
try {
pasvSocket=new ServerSocket(0);
int pPort=pasvSocket.getLocalPort();
if(pPort<1024)
pPort=1025;
pasvSocket.setSoTimeout(10000);
response("227 entering passive mode ("+InetAddress.getLocalHost().getHostAddress().replace(',', '.')+","+pPort+")");
if(pasvSocket!=null)
dataSocket=pasvSocket.accept();
} catch (Exception e) {
if(pasvSocket!=null){
pasvSocket.close();
pasvSocket=null;
}
}
return;
}
//文件下载命令RETR(RETEIEVE)
if(str.startsWith("RETR ")){
Socket dataSocket_retr;
str=getParam(str, "RETR");
str=str.trim();
if(pasvSocket!=null)
dataSocket_retr=pasvSocket.accept();//被动模式
else
dataSocket_retr=new Socket(this.host,this.port);//主动模式
RandomAccessFile inFile=new RandomAccessFile(root+"/"+str, "r");//随机访问文件
OutputStream outSocket=new dataSocket_retr.getOutputStream();//输出流
byte byteBuffer[]=new byte[1024];
int amount_retr;
response("150 opening ascii mode data connection.");
try{
while((amount_retr=inFile.read(byteBuffer)) != -1){//通过随机访问文件,在服务器上读文件
outSocket.write(byteBuffer, 0, amount_retr);//通过输出流,发送到客户端
}
outSocket.close();
inFile.close();
dataSocket_retr.close();
response("226 transfer complete");
}catch(IOException e){
response("550 ERROR:File not found or access denied.");
}
return;
}
//文件上传命令STOR(STORE)
if(str.startsWith("STOR")){
Socket dataSocket_stor;
str=getParam(str, "STOR");
str=str.trim();
if(pasvSocket!=null)
dataSocket_stor = pasvSocket.accept();
else
dataSocket_stor=new Socket(this.host,this.port);
RandomAccessFile inFile=new RandomAccessFile(root+"/"+str, "rw");//随机访问文件
InputStream inSocket=dataSocket_stor.getInputStream();
byte byteBuffer[]=new byte[1024];
int amount_stor;
response("150 binary data connection");
try{
while((amount_stor=inSocket.read(byteBuffer))!=-1){
inFile.write(byteBuffer,0,amount_stor);
}
inSocket.close();
response("226 tranfer complete");
inFile.close();
dataSocket_stor.close();
}catch(IOException e){
response("550 error:file not found or access denied");
}
return;
}
//文件和目录列表LIST命令
if(str.startsWith("LIST")){
Socket dataSocket_list;
if(pasvSocket!=null)
dataSocket_list=pasvSocket.accept();
else
dataSocket_list=new Socket(this.host,this.port);
PrintWriter out=new PrintWriter(dataSocket_list.getOutputStream(), true);

File file=new File(root);
String[] dirStructrue=new String[10];
String strType="";
response("150 opening ascii mode data connection.");
try{
dirStructrue=file.list();
for(int i=0;i<dirStructrue.length;i++){
if(dirStructrue[i].indexOf(".")==-1){
strType="d ";
}
else{
strType="- ";
}
out.println(strType+dirStructrue[i]);//名称发送到客户端
}
out.close();
dataSocket_list.close();
response("226 transfer complete");
}catch(IOException e){
out.close();
dataSocket_list.close();
response(e.getMessage());
}
return;
}


response("500 invalid command");
}

}