-
10.2.4.3 例 3: ネットワーク アプリケーション層プロトコルの開発
清華大学出版局『Java プログラマー、仕事でやるべきこと』著者: Zhong Sheng - 第 10 章「達人は能力に応じて才能がある」からの一部抜粋。
たとえば、図に示すように、「LeapFTP」は非常に便利な FTP サーバーのアップロードおよびダウンロード ツールです。ユーザー名とパスワードを入力すると、FTPサーバー上のファイル一覧が表示され、アップロードやダウンロードの操作が簡単にできる便利なツールです。
Java で FTP ファイルのアップロードおよびダウンロード アプリケーションを作成しようとしたことがありますか?
Java でもこのようなプログラムを開発できます。それは複雑ではありません。まず、Java の FTP ツールキットを使用して FTP アプリケーションを開発する方法を見てみましょう。
sun.net.* をインポートします。
sun.net.ftp.* をインポートします。
パブリック クラス FTP {
public static void main(String[] args) {
String server="192.168.0.12" //FTP サーバーの IP アドレスを入力します
String user="useway" //FTP サーバーにログインするためのユーザー名
String password=" !@#$%abce " //FTP サーバーにログインするためのユーザー名のパスワード
String path="/home/useway" //FTP サーバー上のパス
試す {
FtpClient ftpClient=new FtpClient(); // FtpClient オブジェクトを作成します。
ftpClient.openServer(server); //FTPサーバーに接続します
ftpClient.login(ユーザー, パスワード); //FTPサーバーにログインします。
if (path.length()!=0) ftpClient.cd(path);
TelnetInputStream is=ftpClient.list();
int c;
while ((c=is.read())!=-1) {
System.out.print((char)c);
}
is.close();
ftpClient.closeServer();//FTPサーバーを終了します
}
catch(例外例){
}
}
}
興味があれば、このプログラムを自分で作成してみてください。このプログラムを実行すると、図に示すような状況が表示され、サーバー側プログラムのディレクトリの内容がリストされます。
このプログラムは、FTP サーバー上のファイル一覧を取得する単純なプログラムですが、誤解しないでください。このプログラムは、「ネットワーク アプリケーション層プロトコル」プログラムの開発とは言えません。
このプログラムは、「sun.net.*;」および「sun.net.ftp.*;」内の関連クラスを使用して FTP サーバーに接続するネットワーク レベルでの Java の Socket を使用しません。リクエストはクライアントに送信されますが、リンクリクエストは Java が提供するツールキットを通じてサーバーに送信されます。
Java の FTP パッケージを使用して FTP サーバーに接続する利点は、ネットワーク レベルでのデータ送信の詳細を気にする必要がなく、対応するメソッドを呼び出すだけで済むことです。 Java の FTP パッケージを使用して FTP サーバーに接続する場合の欠点は、開発者がアプリケーション層プロトコルの送受信の詳細を知らず、原理を理解できず、基礎となるデータの把握が非常に弱いことです。
この時点で、一部のプログラマーは「それでは、FTP はネットワーク レベルで PC とサーバーの間でどのように対話するのでしょうか?」と尋ねるでしょう。それでは、FTP プロトコルの対話プロセスを列挙してみましょう。
次の FTP プロトコル対話の例を見てください。
FTP サーバー: 220 (vsFTPd 2.0.1)
FTP クライアント: USER 使用方法
FTPサーバー:331 パスワードを指定してください。
FTP クライアント: PASS !@#$%abce
FTP サーバー: 230 ログインに成功しました。
FTP クライアント: CWD /home/useway
FTP サーバー: 250 ディレクトリが正常に変更されました。
FTP クライアント: EPSV ALL
FTP サーバー: 200 EPSV ALL OK。
FTPクライアント:EPSV
FTP サーバー: 229 拡張パッシブ モードの開始 (|||62501|)
FTPクライアント:リスト
FTP サーバー: 150 ここにディレクトリのリストが表示されます。
FTP サーバー: 226 ディレクトリ送信 OK。
FTP クライアント: 終了
FTP サーバー: 221 さようなら。
上記のテキストは、実際には FTP サーバーと FTP クライアントの間で情報を送信するためのプロトコルであり、相互に送信される内容は上記のテキストに書かれている内容です。
各文の意味をステップごとに説明してみましょう。
FTP サーバー: 220 (vsFTPd 2.0.1) 説明: リンクが成功しました。
FTP クライアント: USER 使用方法 |手順: ユーザー名を入力してください
FTP サーバー: 331 パスワードを指定してください |説明: パスワードを入力してください。
FTP クライアント: PASS !@#$%abce |指示: パスワードを入力してください
FTP サーバー: 230 ログインに成功しました。 |
FTP クライアント: CWD /home/useway 説明: ディレクトリを切り替えます。
FTP サーバー: 250 ディレクトリーが正常に変更されました。 |説明: ディレクトリーの切り替えが成功しました。
FTP クライアント: EPSV ALL 説明: EPSV パッシブ リンク モード
FTP サーバー: 200 EPSV はすべて正常です。
FTP クライアント: EPSV | リンク
FTP サーバー: 229 Entering Extended Passive Mode (|||62501|) |説明: パッシブ リンク ポートは 62501 です。
FTP クライアント: LIST | 説明: LIST を実行してファイル一覧を表示します。
FTP サーバー: 150 ディレクトリのリストが表示されます。 説明: リストはポート 62501 から送信されます。
FTP サーバー: 226 ディレクトリ送信 OK |説明: 送信が完了しました。
FTP クライアント: QUIT | 説明: FTP を終了します。
FTP サーバー: 221 さようなら |
上記の内容で、ツールを使わずに FTP ファイルのリストを取得できます。信じられない場合は、私に従ってもう一度実行してください。
ステップ 1: まず CMD を開いて DOS コマンド ライン モードに入り、次のように入力します。
telnet 192.168.0.1 21[Enter]
説明: FTP サーバーのポート 21 に Telnet します。
このコマンドを実行すると、図に示す結果が得られます。
何か問題は見つかりましたか?
プロンプトの内容は、上の段落の最初の文 220 (vsFTPd 2.0.1) です。これは、FTP サーバーがリンクを受け入れ、次のステップに進むことができることを意味します。
ステップ 2: 次の一連の送信コンテンツを 1 つずつ入力します。
USER 使用法[Enter]
PASS !@#$%abce [Enter]
CWD /home/useway[Enter]
EPSV ALL[入力]
EPSV[入力]
得られた結果を図に示します。
さて、今回は FTP サーバーが一連の応答を返し、最終的に新しいポート番号「58143」を与えました。
ステップ 3: 新しい CMD ウィンドウを開き、次のように入力します。
telnet 192.168.0.1 58143[Enter]
なお、今回サーバーに接続する Telnet リクエストのポート番号は「58143」で、FTP サーバーから与えられたリンクポートです。リンク後、図に示すように、ウィンドウは何も表示されずに空白になります。
ステップ 4: 最初の CMD ウィンドウに戻り、次のように入力します。
リスト[入力]
ステップ 5: この時点で、2 番目の CMD ウィンドウはファイル リストを受け取ります。
2 番目のウィンドウは、図に示すようにファイル リストを受け取ります。
ステップ 6: 操作を終了する
終了[入力]
実行が完了すると、図に示すように、ホストへのリンクが失われます。
ご覧のとおり、FTP プロトコルは対話型プロセスです。システムに付属の Telnet ツールを使用して、FTP のこれらの基本的なコマンド操作を実行することもできます。 Java の Socket を使用して上記の操作を完了する場合は、上記の内容を段階的に実行して文字列を FTP サーバーに送信するだけです。
以下にコード例も示します。
java.io.InputStreamをインポートします。
java.io.OutputStreamをインポートします。
java.net.Socketをインポートします。
パブリック クラス FTPClient{
public static void main(String[] args) throws Exception{
ソケットソケット = new Socket("192.168.0.1",21);
入力ストリームは =ソケット.getInputStream();
OutputStream os = ソケット.getOutputStream();
//初期リンク情報を受け取る
byte[] バッファ = 新しいバイト [100];
int length = is.read(buffer);
文字列 s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//ユーザー名を送信
文字列 str = "ユーザーの使用方法n";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//パスワードを送信
str = "合格!@#$%abcdn ";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//フォルダ切り替えコマンド送信
str = "CWD /home/usewayn";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//モードを設定する
str = "EPSV すべてn";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//パッシブ監視情報を取得する
str = "EPSVn";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//FTPパッシブ監視用のポート番号を取得する
String portlist=s.substring(s.indexOf("(|||")+4,s.indexOf("|)"));
System.out.println(ポートリスト);
// ShowList スレッド クラスをインスタンス化し、FTP パッシブ リスニング ポート番号をリンクします
ShowList sl=新しい ShowList();
sl.port=Integer.parseInt(ポートリスト);
sl.start();
//LISTコマンドを実行
str = "リストn";
os.write(str.getBytes());
//戻り値を取得する
長さ = is.read(バッファ);
s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//リンクを閉じます
is.close();
os.close();
ソケット.クローズ();
}
}
//パッシブ リンク情報クラスを取得します。このクラスはマルチスレッドです
class ShowList extends Thread{
パブリック int ポート = 0;
public void run(){
試す{
ソケットソケット = new Socket("192.168.0.1",this.port);
入力ストリームは =ソケット.getInputStream();
OutputStream os = ソケット.getOutputStream();
byte[] バッファ = 新しいバイト [10000];
int length = is.read(buffer);
文字列 s = 新しい文字列(バッファ, 0, 長さ);
System.out.println;
//リンクを閉じます
is.close();
os.close();
ソケット.クローズ();
}
catch(例外例){
}
}
}
プログラムの実行後に得られる実行結果は図に示すとおりです。これは、カプセル化されたメソッドを解凍して実行するだけです。それらの動作ルールを理解すれば、同じプログラムを開発できます。