⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.java

📁 TCP/IP用java语言实现
💻 JAVA
字号:

import java.net.*;
import java.io.*;

public class Ftp {
	//准备socket
	Socket ctrlSocket;				//控制用socket
	public PrintWriter ctrlOutput;	//控制输出的流
	public BufferedReader ctrlInput;//控制输入的流

	final int CTRLPORT = 21 ;		//控制用端口

	//openConnection方法
	//由地址和端口 构造Socket 形成控制用的流
	public void openConnection(String host)throws IOException,UnknownHostException
	{
		ctrlSocket = new Socket(host, CTRLPORT);//21
		ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream());
		ctrlInput  = new BufferedReader(new InputStreamReader
							(ctrlSocket.getInputStream()));
	}

	public void closeConnection()
		throws IOException
	{
		ctrlSocket.close() ;
	}
	
	//showMenu 立法
	//输出 FTP 的命令菜单
	public void showMenu()
	{
		System.out.println("~~~~~~~~~~~~~~>  命令格式  <~~~~~~~~~~~~~~~") ;
		System.out.print("1 dir ;") ;
		System.out.print(" 2 cd ;") ;
		System.out.print(" 3 pwd ;") ;
		System.out.print(" 4 cdup ;") ;
		System.out.print(" 5 mkd ;") ;
		System.out.print(" 6 get ;") ;
		System.out.println(" 7 put .") ;
		System.out.println(" 8 asc .") ;
		System.out.println(" 9 bin .") ;
		System.out.println(" 10 abor .") ;
		System.out.println(" 11 dele .") ;
		System.out.println(" 12 quit .") ;
	}

	// getCommand方法
	// 读用户指定的命令序号
	public String getCommand()
	{
		String buf = "" ;
		//从键盘输入
		BufferedReader lineread	= new BufferedReader(new InputStreamReader(System.in)) ;

		//while(buf.length() != 1){			// 循环接收一个字符的输入
			try{
				buf = lineread.readLine() ;
			}catch(Exception e)
			{
				e.printStackTrace();
				System.exit(1);
			}
		//}
		return (buf) ;
	}

	// doLogin方法
	// 登陆FTP 服务器
	public void doLogin()
	{
		String loginName = "" ;
		String password = "" ;
		BufferedReader lineread	= new BufferedReader(new InputStreamReader(System.in)) ;
		try{
			System.out.println("请输入用户名") ;
			loginName = lineread.readLine() ;
			ctrlOutput.println("USER " + loginName) ;
			ctrlOutput.flush() ;			//刷新流
			System.out.println("请输入口令") ;
			password = lineread.readLine() ;
			ctrlOutput.println("PASS " + password) ;
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// doQuit方法
	// 向Ftp 注销
	public void doQuit()
	{
		try{
			ctrlOutput.println("QUIT ") ;// 发送 QUIT 命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// doCd方法
	// 切换目录
	public void doCd()
	{
		String dirName = "" ;
		BufferedReader lineread	= new BufferedReader(new InputStreamReader(System.in)) ;

		try{
			System.out.println("请输入目录名:") ;
			dirName = lineread.readLine() ;
			ctrlOutput.println("CWD " + dirName) ;// CWD命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	//doCdup
	//上一层目录
	public void doCdup()
	{
		try{
			ctrlOutput.println("CDUP ") ;// CDUP命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	//显示当前目录
	public void doPwd()
	{
		try{
			ctrlOutput.println("PWD ") ;// PWD命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	//强行关闭当前的传送数据的Socket
	public void doAbor()
	{
		try{
			ctrlOutput.println("ABOR ") ;// ABOR命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	//删除服务器上的指定文件
	public void doDele()
	{
		String dirName = "" ;
		BufferedReader lineread	= new BufferedReader(new InputStreamReader(System.in)) ;

		try{
			System.out.println("请输入要删的文件名或目录名:") ;
			dirName = lineread.readLine() ;
			ctrlOutput.println("DELE " + dirName) ;// CWD命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	////建立目录
	public void doMkd()
	{
		String dirName = "" ;
		BufferedReader lineread	= new BufferedReader(new InputStreamReader(System.in)) ;

		try{
			System.out.println("请起个目录名:") ;
			dirName = lineread.readLine() ;
			ctrlOutput.println("MKD " + dirName) ;// CWD命令
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}


	// doLs方法
	// 取得目录信息
	public void doLs()
	{
		try{
			int n ;
			byte[] buff = new byte[1024] ;

			// 建立数据连接
			Socket dataSocket = dataConnection("LIST") ;
			// 准备读取数据用流
			BufferedInputStream dataInput
							= new BufferedInputStream(dataSocket.getInputStream()) ;
			// 读取目录信息
			while((n = dataInput.read(buff)) > 0){
				System.out.write(buff,0,n) ;
			}
			dataSocket.close() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// dataConnection方法
	// 构造与服务器交换数据用的socket
	// 再用 PORT 命令将端口号通知给服务器
	public Socket dataConnection(String ctrlcmd)
	{
		String cmd = "PORT " ; //存贮发送PORT命令的数据 所用的变量
		int i ;
		Socket dataSocket = null ;
		try{
			// 取得自己用的地址
			byte[] address = InetAddress.getLocalHost().getAddress() ;
			// 用适当的端口号构造服务器 Socket
			ServerSocket serverDataSocket = new ServerSocket(0,1) ;
			// 准备传送port 命令用的数据
			for(i = 0; i < 4; ++i)
				cmd = cmd + (address[i] & 0xff) + "," ;
			cmd = cmd + (((serverDataSocket.getLocalPort()) / 256) & 0xff)
					  + ","
					  + (serverDataSocket.getLocalPort() & 0xff) ;
			// 利用控制用的流发送PORT命令
			ctrlOutput.println(cmd) ;
			ctrlOutput.flush() ;
			// 向服务器发送处理对象命令(LIST,RETR及STOR)
			ctrlOutput.println(ctrlcmd) ;
			ctrlOutput.flush() ;
			// 受理服务器的连接
			dataSocket = serverDataSocket.accept() ;
			serverDataSocket.close() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
		return dataSocket ;
	}

	// doAscii方法
	// 设置文本传输模式
	public void doAscii()
	{
		try{
			ctrlOutput.println("TYPE A") ;// A模式
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// doBinary方法
	// 设置二进制传输模式
	public void doBinary()
	{
		try{
			ctrlOutput.println("TYPE I") ;// I模式
			ctrlOutput.flush() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// doGet方法
	//  取得服务器上的文件
	public void doGet()
	{
		String fileName = "" ;
		BufferedReader lineread
			= new BufferedReader(new InputStreamReader(System.in)) ;
		try{
			int n ;
			byte[] buff = new byte[1024] ;
			// 指定报务器上文件的名
			System.out.println("请输入文件名") ;
			fileName = lineread.readLine() ;
			// 在客户端上准备存储其内容的文件
			FileOutputStream outfile = new FileOutputStream(fileName) ;
			// 构造传输文件用的数据流
			Socket dataSocket = dataConnection("RETR " + fileName) ;
			BufferedInputStream dataInput
				= new BufferedInputStream(dataSocket.getInputStream()) ;
			// 从服务器上读取数据并存储到文件中
			while((n = dataInput.read(buff)) > 0){
				outfile.write(buff,0,n) ;
			}
			dataSocket.close() ;
			outfile.close() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	// doPut方法
	// 向服务器发送文件
	public void doPut()
	{
		String fileName = "" ;
		BufferedReader lineread
			= new BufferedReader(new InputStreamReader(System.in)) ;

		try{
			int n ;
			byte[] buff = new byte[1024] ;
			FileInputStream sendfile = null ;

			// 指定文件名:
			System.out.println("请输入文件名:") ;
			fileName = lineread.readLine() ;
			// 准备读出客户端的文件
			try{
				sendfile = new FileInputStream(fileName) ;
			}catch(Exception e){
				System.out.println("文件不存在") ;
				return ;
			}

			// 准备发送数据用的流
			Socket dataSocket = dataConnection("STOR " + fileName) ;
			OutputStream outstr = dataSocket.getOutputStream() ;
			// 读出文件,经由网络发送给服务器
			while((n = sendfile.read(buff)) > 0){
				outstr.write(buff,0,n) ;
			}
			dataSocket.close() ;
			sendfile.close() ;
		}catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	// execCommand方法
	// 调用与命令对应的各种处理方法
	public boolean execCommand(String command)
	{
		boolean cont = true ;

		switch(Integer.parseInt(command)){
		case 1 :  // 显示服务器目录信息
			doLs() ;
			break ;
		case 2 :  // 切换服务器上的工作目录
			doCd() ;
			break ;
		case 3 :  // 显示当前目录
			doPwd() ;
			break ;
		case 4:	  //上层目录
			doCdup() ;
			break ;
		case 5 :  // 新建目录
			doMkd() ;
			break ;
		case 6 :  // 从服务器上取得文件
			doGet() ;
			break ;
		case 7 :  // 向服务器发送文件
			doPut() ;
			break ;
		case 8 :  // 文件传输模式
			doAscii() ;
			break ;
		case 9 :  // 二进制模式
			doBinary() ;
			break ;
		case 10 : // 强关dataSocket 流
			doAbor() ;
			break ;
		case 11 : // 删除服务器上的指定文件
			doDele() ;
			break ;
		case 12 : // 处理结束
			doQuit() ;
			cont = false ;
			break ;
		default : //其他的输入
			System.out.println("请选择一个序号") ;
		}
		return(cont) ;
	}

	// main_proc方法
	// 输出 Ftp 的命令菜单并进行各种处理
	public void main_proc()	throws IOException
	{
		boolean cont = true ;
		try {
			doLogin() ;							// 进行登录
			while(cont){
			showMenu() ;						// 输出菜单
			cont = execCommand(getCommand()) ;	//接收并执行命令
			}
		}
		catch(Exception e){
			System.err.print(e);
			System.exit(1);
		}
	}
	// getMsgs 立法
	// 启动接收控制流的线程式
	public void getMsgs(){
		try {
			CtrlListen listener = new CtrlListen(ctrlInput) ;
			Thread listenerthread = new Thread(listener) ;
			listenerthread.start() ;
		}catch(Exception e){
			e.printStackTrace() ;
			System.exit(1) ;
		}
	}

	// main方法
	// 建立TCP连接,开始处理
	public static void main(String[] arg){
		try {
			Ftp f = null;

			if(arg.length < 1){
				System.out.println("用法: java Ftp <host name>") ;
				return ;
			}
			f = new Ftp();
			f.openConnection(arg[0]); // 建立控制连接
			f.getMsgs() ; 			  //启动接收线程
			f.main_proc(); 			  // ftp 处理
			f.closeConnection() ; 	  // 关闭连接
			System.exit(0) ; 		  // 结束程序
		}catch(Exception e){
			e.printStackTrace();
			System.exit(1);
		}
	}
}

// CtrlListen 类
class CtrlListen implements Runnable{
	BufferedReader ctrlInput = null ;
	// 构造器,指定读取地点
	public CtrlListen(BufferedReader in){
		ctrlInput = in ;
	}

	public void run(){
		while(true){
			try{ 					  // 按行读入并写到标准输出上
				System.out.println(ctrlInput.readLine()) ;
			} catch (Exception e){
				System.exit(1) ;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -