Newer
Older
myNWP2 / src / j3 / MyFTP.java
@Motoki Miura Motoki Miura on 22 Sep 2020 11 KB first commit for NWP exp
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