FTP服务器端的实现

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");
	}
	
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值