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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章