Newer
Older
test001 / MyFTP.java
@Motoki Miura Motoki Miura on 7 Aug 2020 10 KB java files
// 機能 : ftp サーバと接続してファイル転送を行う
// 使い方: java MyFTP <サーバ名>
// 起動例: java MyFTP ftp.ne.jp

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

public class MyFTP {
	Socket ctrlSocket;		//制御用ソケット
	public PrintWriter ctrlOutput;	//制御出力用ストリーム
	public BufferedReader ctrlInput;// 同入力用ストリーム

	final int CTRLPORT = 21 ;// ftp の制御用ポート
	//------------------------------------------------------------------
	//アドレスとポート番号からソケットを作り制御用ストリームを作成
	public void openConnection(String host)
		throws IOException,UnknownHostException {
		ctrlSocket = new Socket(host, CTRLPORT);
		ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream());
		ctrlInput
			= new BufferedReader(new
				InputStreamReader(ctrlSocket.getInputStream()));
	} // end of openConnection
	//------------------------------------------------------------------
	//制御用のソケットを閉じる
	public void closeConnection() throws IOException {
		ctrlSocket.close() ;
	} // end of closeConnection
	//------------------------------------------------------------------
	// ftp サーバにログイン
	public void doLogin() {
		String loginName = "" ;
		String password = "" ;
		BufferedReader lineread
			= new BufferedReader(new InputStreamReader(System.in)) ;

		try {
			System.out.println("ログイン名を入力してください") ;
			loginName = lineread.readLine() ;
			// USERコマンドによるログイン
			ctrlOutput.println("USER " + loginName) ;
			ctrlOutput.flush() ;
			// PASSコマンドによるパスワードの入力
			System.out.println("パスワードを入力してください") ;
			password = lineread.readLine() ;
			ctrlOutput.println("PASS " + password) ;
			ctrlOutput.flush() ;
		} catch(Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	} // end of doLogin
	//------------------------------------------------------------------
	// ftp サーバからログアウト
	public void doQuit() {
		try {
			ctrlOutput.println("QUIT ") ;// QUITコマンドの送信
			ctrlOutput.flush() ;
		} catch(Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	} // end of doQuit
	//------------------------------------------------------------------
	// ディレクトリを変更
	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);
		}
	} // end of doCd
	//------------------------------------------------------------------
	// ディレクトリ情報を取得
	public void doLs(){
		int n ;
		byte[] buff = new byte[1024] ;
		try {
			// データ用コネクションを作成
			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);
		}
	} // end of doLs
	//------------------------------------------------------------------
	// サーバとのデータ交換用にソケットを作ります
	// また,サーバに対してportコマンドでポートを通知します
	public Socket dataConnection(String ctrlcmd)
	{
		String cmd = "PORT " ; //PORTコマンドで送るデータの格納用変数
		int i ;
		Socket dataSocket = null ;// データ転送用ソケット
		try {
			// 自分のアドレスを求める
			byte[] address = InetAddress.getLocalHost().getAddress() ;

			// 適当なポート番号のサーバソケットを作成
			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 ;
	} // end of dataConnection
	//------------------------------------------------------------------
	// サーバ上のファイルを取得
	public void doGet() {
		String fileName = "" ;
		BufferedReader lineread
		= new BufferedReader(new InputStreamReader(System.in)) ;
			int n ;
			byte[] buff = new byte[1024] ;

		try {
			// サーバ上ファイルのファイル名を指定します
			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);
		}
	} // end of doGet
	//------------------------------------------------------------------
	// サーバへファイルを送ります
	public void doPut() {
		String fileName = "" ;
		BufferedReader lineread
			= new BufferedReader(new InputStreamReader(System.in)) ;
		int n ;
		byte[] buff = new byte[1024] ;

		try {
			System.out.println("Input File Name: ") ;
			fileName = lineread.readLine() ;

			// クライアント上のファイルの読み出し準備を行います
			FileInputStream sendfile = new FileInputStream(fileName) ;

			// 転送用データストリームを用意します
			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);
		}
	} // end of doPut
	//------------------------------------------------------------------
	// Ftp のコマンドメニューを出力
	public void showMenu()
	{
		System.out.println("Input Command: ") ;
		System.out.print("1(login)") ;
		System.out.print("   2(ls)") ;
		System.out.print("   3(cd)") ;
		System.out.print("   4(get)") ;
		System.out.print("   5(put)") ;
		System.out.println("   9(quit)") ;
	} // end of showMenu
	//------------------------------------------------------------------
	// コマンドを入力
	public String getCommand()
	{
		String buf = "" ;
		BufferedReader lineread
			= new BufferedReader(new InputStreamReader(System.in)) ;
		while(buf.length() != 1){// 1文字の入力を受けるまで繰り返し
			try {
				buf = lineread.readLine() ;
			} catch(Exception e) {
				e.printStackTrace();
				System.exit(1);
			}
		}
		return (buf) ;
	} // end of getCommand
	//------------------------------------------------------------------
	// コマンドに対応する各処理を呼び出す
	public boolean execCommand(String command)
	{
		boolean cont = true ;
		switch (Integer.parseInt(command)){
		case 1 : // login 処理
			doLogin() ;
			break ;
		case 2 : // サーバのディレクトリ表示処理
			doLs() ;
			break ;
		case 3 : // サーバの作業ディレクトリ変更処理
			doCd() ;
			break ;
		case 4 : // サーバからのファイル取得処理
			doGet() ;
			break ;
		case 5 : // サーバへのファイル転送処理
			doPut() ;
			break ;
		case 9 : // 処理の終了
			doQuit() ;
			cont = false ;
			break ;
		default : //それ以外の入力
			System.out.println("番号を選択してください") ;
		}
		return(cont) ;
	} // end of execCommand
	//------------------------------------------------------------------
	// Ftp のコマンドメニューを出力して,各処理を呼び出します
	public void main_proc()
		throws IOException
	{
		boolean cont = true ;
		try {
			while(cont){
				// メニューを出力します
				showMenu() ;
				// コマンドを受け取り実行します
				cont = execCommand(getCommand()) ;
			}
		}
		catch (Exception e) {
			System.err.print(e);
			System.exit(1);
		}
	} // end of main_proc
	//------------------------------------------------------------------
	// 制御ストリームの受信スレッドを開始します
	public void getMsgs(){
		try {
			CtrlListen listener = new CtrlListen(ctrlInput) ;
			Thread listenerthread = new Thread(listener) ;
			listenerthread.start() ;
		} catch (Exception e) {
			e.printStackTrace() ;
			System.exit(1) ;
		}
	} // end of getMsgs
	//------------------------------------------------------------------
	// TCPコネクションを開いて処理を開始します
	public static void main(String[] arg){
		if (arg.length != 1) {
			System.out.println("Usage: MyFTP <server addr>");
			System.exit(1);
		}
		try {
			MyFTP f = null;
			f = new MyFTP();
			f.openConnection(arg[0]);	// 制御用コネクションの設定
			f.getMsgs() ;				// 受信スレッドの開始
System.out.println("309");
			f.main_proc();				// ftp 処理
System.out.println("311");

			f.closeConnection() ;		// コネクションのクローズ
			System.exit(0) ;			// プログラムの終了
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	} // end of main
} // end of class MyFTP
//=============================================================================
// 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) ;
			}
		}
	}
} // end of class CtrlListen