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