package j3; // 機能 : 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