前へ << echo サーバを作ってみよう (4) | FTP クライアントを作ってみよう (2) >> 次へ |
まずは ftp コマンドを使って、ftp する際の挙動をおさらいしましょう。 詳しい使い方は説明しませんが、あなたは今から ftp クライアントを作ろう としている人ですから、大丈夫ですよね?
UNIX にも Windws にも ftp コマンドは標準で用意されているはずです。 以下は、ftp.hoge.com にログインして、file1.txt を get (ダウンロード) し、 program を put (アップロード) する例です。
% ftp ftp.hoge.com Connected to ftp.hoge.com. 220 ftp FTP server (Version 6.00) ready. Name (ftp.hoge.com:username): username 331 Password required for username. Password: password 230 User username logged in. Remote system type is UNIX. Using binary mode to transfer files.ユーザ名とパスワードを入力して、ログインすることができました。 lsでファイル・ディレクトリの一覧を表示してみます。
ftp> ls 200 PORT command successful. 150 Opening ASCII mode data connection for '/bin/ls'. total 464 -rw-r--r-- 1 user user 130 Jan 9 10:36 file.txt drwxr-xr-x 3 user user 512 Dec 14 00:29 dir 226 Transfer complete.ファイル file.txt と、ディレクトリ dir が存在することがわかりました。 ではfile.txtをダウンロードします。ただし、file.txt はテキストファイルなので、 ASCII モードにしましょう。その後 get file.txt とすることで、 ローカルへのファイル転送ができます。
ftp> ascii 200 Type set to A. ftp> get file.txt local: file.txt remote: file.txt 200 PORT command successful. 150 Opening BINARY mode data connection for 'file.txt' (130 bytes). 226 Transfer complete.今度はローカルから ftp.hoge.com へ、ファイル program をアップロードします。 これはコンパイル済のバイナリファイルですから、binary でバイナリ転送モードに 切り替えます。
ftp> binary 200 Type set to I. ftp> put program local: program remote: program 200 PORT command successful. 150 Opening ASCII mode data connection for 'program'. 226 Transfer complete.転送はうまくいったはずですが、念のためもう一度 ls を実行して、 本当に program が転送されたかどうか調べましょう。
ftp> ls 200 PORT command successful. 150 Opening ASCII mode data connection for '/bin/ls'. total 464 -rw-r--r-- 1 user user 130 Jan 9 10:36 file.txt drwxr-xr-x 3 user user 512 Dec 14 00:29 dir -rw-r--r-- 1 user user 65536 Dec 4 08:09 programOK ですね。では bye で ftp コマンドを終了します。
ftp> bye 221 Goodbye.
先ほどはタイプする部分を太字で表記しましたが、今度は デバッグ表示もあわせて bold 表記します。
% ftp -d ftp.hoge.com Connected to fto.hoge.com. 220 ftp FTP server (Version 6.00) ready. Name (ftp.hoge.com:username): username ---> USER username 331 Password required for username. Password: password ---> PASS XXXX 230 User username logged in. ---> SYST 215 UNIX Type: L8 Version: BSD-199506 Remote system type is UNIX. Using binary mode to transfer files. ftp> ls ---> PORT 10,0,0,1,156,87 200 PORT command successful. ---> LIST 150 Opening ASCII mode data connection for '/bin/ls'. total 466 -rw-r--r-- 1 user user 130 Dec 18 03:42 file.txt drwxr-xr-x 3 user user 512 Dec 14 00:29 dir 226 Transfer complete. ftp> ascii ---> TYPE A 200 Type set to A. ftp> get file.txt local: file.txt remote: file.txt ---> SIZE file.txt 213 132 ---> PORT 10,0,0,1,156,88 200 PORT command successful. ---> RETR file.txt 150 Opening ASCII mode data connection for 'file.txt' (130 bytes). 226 Transfer complete. ---> MDTM file.txt 213 19981217184250 ftp> binary ---> TYPE I 200 Type set to I. ftp> put program local: program remote: program ---> PORT 10,0,0,1,156,89 200 PORT command successful. ---> STOR program 150 Opening BINARY mode data connection for 'h2z'. 226 Transfer complete. ftp> ls ---> TYPE A 200 Type set to A. ---> PORT 10,0,0,1,156,90 200 PORT command successful. ---> LIST 150 Opening ASCII mode data connection for '/bin/ls'. total 466 -rw-r--r-- 1 user user 130 Jan 9 10:36 file.txt drwxr-xr-x 3 user user 512 Dec 14 00:29 dir -rw-r--r-- 1 user user 65536 Dec 4 08:09 program 226 Transfer complete. ftp> bye ---> QUIT 221 Goodbye.どうですか? FTP プロトコルを知らない人でも、
ぱっと見た感じではよくわからないのが MDTM ですが、 MDTM はファイルのダウンロード時に使われており、さらに
---> MDTM file.txt 213 19981217184250と、日付と時間 (1998/12/17 18:42:50) らしき返事がサーバから返って きています。file.txt のタイムスタンプが
-rw-r--r-- 1 user user 130 Dec 18 03:42 file.txtであることから、これはファイルの最終更新時刻を取得しているようです。 9 時間ずれているのは、相手のマシンが日本標準時間 (JST) となっているから でしょう。
また、SIZE はファイルサイズを取得するコマンドのようです。
---> SIZE file.txt 213 132130 ではなく 132 なのは、ASCII モードで転送したため、 改行コード2つ分のサイズが増えたものと思われます。
さて、あとわからないのは、PORT コマンドだけですね。
---> PORT 10,0,0,1,156,87 ---> PORT 10,0,0,1,156,88 ---> PORT 10,0,0,1,156,89 ---> PORT 10,0,0,1,156,90実は、これが FTP プロトコルの面倒なところです。
FTP プロトコルは、2本のコネクションを使います。 一つはコマンド転送用、もう一つはデータ転送用です。 図で説明しましょう。上から順にプロトコルの流れを見ていってください。
FTP クライアント FTP サーバ USER ------ コマンド用コネクション ------> PASS ------ コマンド用コネクション ------> PORT ------ コマンド用コネクション ------> LIST ------ コマンド用コネクション ------> <----- データ用コネクション(1) ----- ファイル一覧送信 PORT ------ コマンド用コネクション ------> RETR ------ コマンド用コネクション ------> <----- データ用コネクション(2) ----- ファイル内容送信 QUIT ------ コマンド用コネクション ------>わかりますか? LIST やファイル一覧を取得したり、RETR でファイルを 取得する場合は、 FTP サーバが FTP クライアント側に接続してくる のです。そしてその FTP サーバ側からのコネクションの中で、データの送信が 行われるわけです。
しかし何度も書きましたが、サーバとしてクライアントを待つためには、 特定のポートを見張っておかなくてはなりません。しかしFTPサーバは FTP クライアント側のポート何番に接続すればいいのかわかりません。 そこで 「こっちはこのホストのポート何番で待っているから接続してきてね」と FTP クライアントがFTP サーバに連絡するのが PORT コマンドなのです。
---> PORT 10,0,0,1,156,87この例では、前半4つの数字が IP アドレス、後半の2つがポート番号を表します。 前半の4つはそのまま IP アドレスになりますが、後半の2つの数字は、 「156×256+87」で計算される 40023 というポート番号を表しています。 つまり
---> PORT 10,0,0,1,156,87は、「IP アドレス 10.0.0.1 のポート 40023 番を見張っているので、 データはそこに送ってね」と、「FTP クライアントが FTP サーバに連絡している」のです。 その後に LIST コマンドを送るか RETR コマンドを送るかで、データの内容は 変わってきますが、とにかく「そこで待ってるよ」というクライアントの 意志表示なわけです。
PORT 10,0,0,1,156,87 LISTという内容をクライアントがサーバに送信したとき、 「IP アドレス10.0.0.1のポート40023番を見張っているので、 データはそこに送ってね」 「ファイルの一覧を送ってね」 という意味になります。当然ですが、クライアント側は PORT コマンドで宣言したホストの宣言したポートを 見張っていなくてはいけません。
その後、FTP サーバは言われた通りの場所 (IP アドレス 10.0.0.1 のポート 40023 番)に connect し、データ(この場合はファイル一覧)を送ってくるわけです。
まずユーザ認証。
---> USER username ---> PASS XXXX
---> SYSTls がタイプされたので、ファイル一覧を取得します。 IP アドレス 10.0.0.1 のポート 40023 番 (156×256+87) で待っていることを宣言し、 実際にそのポートを見張ります。
---> PORT 10,0,0,1,156,87そしてファイル一覧を送るよう要求します。
---> LISTここで FTP サーバ側は IP アドレス 10.0.0.1 のポート 40023 番に接続し、 ファイル一覧を送信します。送信が終ると、そのコネクションは切断されます。
ascii とタイプされたので、TYPE A で ASCII モードにします。
---> TYPE A次に get file.txt とタイプされたので、file.txt をダウンロードします。 まずファイルサイズを取得します。 次に IP アドレス 10.0.0.1 のポート 40024 番 (156×256+88) で待っていることを宣言し、 実際にそのポートを見張ります。
---> SIZE file.txt ---> PORT 10,0,0,1,156,88そして file.txt を送るよう要求します。
---> RETR file.txtここで FTP サーバ側は IP アドレス 10.0.0.1 のポート 40024 番に接続し、 file.txt の内容を送信します。送信が終ると、そのコネクションは切断されます。
---> MDTM file.txtbinary とタイプされたので、BINARY モードに切替えます。
---> TYPE Iput program とタイプされたので、ファイル program を アップロードします。 IP アドレス 10.0.0.1 のポート 40025 番 (156×256+89) で待っていることを宣言し、 実際にそのポートを見張ります。
---> PORT 10,0,0,1,156,89そして今からファイル program を送ることを伝えます。
---> STOR programFTP サーバ側は IP アドレス 10.0.0.1 のポート 40025 番に接続します。 クライアント側は接続があると program の内容を送信します。 送信が終ると、そのコネクションは切断されます。
---> TYPE A再度 ls がタイプされたので、ファイル一覧を取得します。 IP アドレス 10.0.0.1 のポート 40026 番 (156×256+90) で待っていることを宣言し、 実際にそのポートを見張ります。
---> PORT 10,0,0,1,156,90そしてファイル一覧を送るよう要求します。
---> LISTFTP サーバ側は IP アドレス 10.0.0.1 のポート 40026 番に接続し、 ファイル一覧を送信します。送信が終ると、そのコネクションは切断されます。
bye とタイプされたので、コネクション切断を知らせます。
---> QUIT最初に張られたコネクションは QUIT が送られるまで 繋がったままで、コマンド用コネクションとして機能していることに 注意してください。途中で「切断されます」と書いたのは、 データ用コネクションのことです。
どうでしょう。理解できましたか?
前へ << echo サーバを作ってみよう (4) | FTP クライアントを作ってみよう (2) >> 次へ |
ご意見・ご指摘は Twitter: @68user までお願いします。