RFC959(STD9)からの抜粋これは簡単なFTPの動作概念図だ。述べたように、FTPはクライアント/サーバモデルを採っている。クライアントとサーバ双方に「PI」と呼ばれるモジュールが存在している。PIは「プロトコル・インタプリタ」という意味で、クライアントからの命令やサーバへの指示を、実際のプロトコルへと「翻訳」するためのものだ。皆さんは普段どんなツールからFTPを利用しているだろうか。Interface)のFTPコマンドか、それともGUIのFTPツールか、あるいはWebブラウザでの利用だろうか。CUIのFTPコマンドであれば、「dir(ディレクトリの表示)」や「mget(複数ファイルの取得)」などを入力して利用することになる。クライアント側PIはこれらユーザーからのFTPコマンドを解釈して、それをFTPのプロトコルへ変換し、サーバへと命令するのだ。サーバ側PIでは、プロトコルの内容をサーバ側での動作に変換して、指定された動作を実行する。先ほどのmgetコマンドは、サーバまで直接届いているわけではない。PIによって解釈され、実際には別のコマンド(つまりFTPのプロトコル)が裏で実行されているのだ。後述するが、mgetのように「複数のファイルを転送する」というプロトコルはFTPには存在していない。内部では、これを複数の「単一ファイルの転送」処理に分割して実行しているのだ。HTTPやSMTPに比べると(プロトコル自体にはそれほどのインパクトはないものの)、何とも面倒な実装をクライアントやサーバのプログラムで行わないといけないわけだ。これには3つの利点がある。1つは、PI(特にクライアント側)によって、CUIのコマンドやGUIツールといった異なるインターフェイスを持つFTPクライアントが、同じプロトコル実装部分を共有できることだ。いうなれば、プレゼンテーション層とロジック層の分離である。さまざまなAPIが流通している現在ではメリットは薄いが、特にFTPが開発された初期には、こうしたロジックの共通化はFTPの一般化に有効であった。Proccess:使用されるファイルシステムのアクセス部分)を切り離し、個々のOSごとの実装が可能となる。これも現在でこそ問題になることは少ないが、一口にファイルの転送といっても、実はOSごとにファイルシステムの仕組みや実装は異なる。単なるテキストファイルであっても、格納構造やフォーマットはOSごとにそれぞれ異なっているのが普通だ。転送しただけでは、相手が別のOSだったとして、そのまま利用できる保証はない。したファイルアクセス部分をモジュール化し、転送時にはその差異をDTPで吸収して変換することで、多様なOSに対応できるマルチプラットフォーム化を目指すという意図なのだ。3番目に、プロトコル自体を明らかに単純にできる。FTPクライアントでは単純なプロトコルを組み合わせることで、より複雑な動作を実行できるからだ。プロトコルの簡易さは組み合わせによるクライアントプログラムの多様化を実現でき、プロトコルの浸透にも役立つことになる。コントロールとデータもう一点、FTPの大きな特徴が、「コントロールコネクション」と「データコネクション」の分離だ。一度、先の図1を見てほしい。クライアント側のユーザーPIは、サーバ側のサーバPIとコネクションを作成する。通常、サーバではポート21番を使用し、ユーザーからのアクセスを待ち受けている。これを「コントロールコネクション」と呼び、HTTPやSMTPと同じようにクライアントからのコマンドを受け入れ、結果ステータスなどを返答する。実際のファイルデータの転送やファイル一覧データなどは、DTPが担当する「データコネクション」を通じて行われる。HTTPやSMTPでは常に1つでしかない接続が、FTPでは2つ利用されるのだ。コントロールとデータの使い分けデータコネクションが別に存在しているのは、コントロールコネクションを通じて、データの転送などの制御をスムーズに行うためだ。データの転送をデータコネクションで行うようにすると、途中でキャンセルなどの介入を行いたい場合に、コントロールコネクションを通じてサーバへ命令することができる。コネクションが1つであれば、大容量ファイルの転送中などにその処理を終了したくなっても、サーバへ指示する術がなく、転送終了までユーザーは待ち続けなければならないだろう。データコネクションで送受信されるのは、あくまで送受信するファイル内容とファイル一覧の結果だけだ。結果ステータスなどは、コントロールコネクションを通じて返答されるので注意しよう。いくぶん複雑ではあるが、非常に洗練されたメカニズムを持つ、インターネット・プロトコル“らしからぬ”プロトコル、それがFTPなのだ。基本フローとコマンドプロトコルの構造や思想が、ほかのインターネット・プロトコルとは異なっている点は理解していただけたかと思う。実際のプロトコル内容にそれほどの違いはない。FTPもやはりTelnetをベースにしており、ASCIIコードをベースとしたコマンドとレスポンスによって実現されている点では同じだ。FTPにおいても、リクエストはコマンドとオプションからなる単一行のテキスト(ASCII)だ。レスポンスは次のようなフォーマットをとる。(メッセージやステータス)レスポンスコードは3桁の応答結果を示す番号だ。個別に番号に対応する意味が定められている。レスポンスが複数行に渡る場合には、レスポンスコードに続く空白が「-(ハイフン)」となり、次に続く行があることを示す。レスポンスコードに空白が続く行の登場により、最終行であることを示している。レスポンスコードは次のカテゴリーに従って決められている。レスポンスコードの詳細は別表1にもまとめた(こちらをクリックすると、別ウィンドウでレスポンスコードの一覧を表示しますをクリックすると、別ウィンドウでレスポンスコードの一覧を表示します)。レスポンスコードのカテゴリーでは、基本的なプロトコルフローの例とその動作を見てみよう。認証と処理の終了クライアントはまず、サーバのコントロールコネクションに接続しなければならない。その際に認証に用いるのがUSERコマンドとPASSコマンドだ。ここでは、ユーザー名とパスワードを指定する。一般には、このときに指定したユーザー権限でサーバのファイルへとアクセスできる。QUITコマンドはコントロールコネクションと、その際に存在していればデータコネクションをクローズする。パスワードQUITデータコネクションの作成と利用PORTコマンドは、サーバにデータコネクションのためのIPアドレスとポート番号を通知するためのコマンドだ。データコネクションは、前述のように、ファイルデータの送信と受信、ファイル一覧情報の取得などを行うための専用コネクションである。IPアドレスとポート番号コントロールコネクションは、まずクライアントからサーバへ向けて作成される。これは一般的なクライアント/サーバモデルに基づいている。次にクライアントはファイルの送受信などに先駆けて、PORTコマンドを実行する必要がある。PORTコマンドは次のようなフォーマットの引数をとる。25第1引数から第4引数まではIPアドレスを示す。4バイトのIPアドレスの各バイトを10進数で表記したものだ。通常は、クライアントのIPアドレスを指定する。上記の例では、「192.168.1.10」という意味になる。第5引数と第6引数は、2バイトのポート番号の各バイトを10進数で表記したものだ。上記であれば、「4×256+25=1049」を示している。データコネクションにおいては、先のコントロールコネクションとは逆に、サーバからクライアントに向けてコネクションを作成する仕様になっている*1。一般のクライアント/サーバとは逆の方向でデータコネクションは張られるのだ。クライアントはあらかじめIPアドレスと使用するポートをサーバに知らせ、そのポートでデータコネクションの受け入れ用ソケットをオープンしておく。サーバはそのポートに対してデータコネクションを作成し、データの送受信を行う、というわけだ。データコネクションはファイルの送受信のたびに作成する必要がある。ファイルの送受信などに先立って毎回PORTコマンドが必要になるのだ。データコネクションでのサーバ側ポート(接続元ポート)は、通常、20番が用いられることになっている。*1厳密には、この説明はあまり正確ではないかもしれない。正しくは、FTPクライアントプログラムは「データコネクション向けサーバとしても動作する」ということになる。逆にFTPサーバプログラムは、データコネクションのためのクライアント機能も持ち、データコネクションに関してはクライアントとして動作する。それぞれがクライアント/サーバの両方の機能を有しているのだ。HTTPやPOPクライアントに比べると、複雑な仕様であることが分かってもらえるだろうデータタイプの指定データタイプというのは、「データの変換モード」の選択だと思えばよい。この機能はよく知られているだろう。一般には、アスキー(ASCII)かバイナリ(イメージとも呼ばれる)かを選択することになる。データタイプアスキーモードの元々の意味は、テキストデータに含まれる改行コードなどOSに依存したコードを、OSに依存しない共通の体系へ変換して送信することを目的としている。した共通体系は「NVT-ASCII」と呼ばれ、実はTelnet仕様でのコード体系と等しい(つまりはASCIIだ)。送信時には、元々の体系からこうした共通体系へ一度変換し、受信時には再びそれぞれのOS依存型へと再変換することで、個々のOSに対応した送受信環境を実現している。UNIXとWindowsで改行コードが異なっても、アスキーモードで送受信することで改行コードがちゃんと変換されるのは、変換時にそれぞれのOSの改行コードへと相互変換しているからなのである。これに対してバイナリでは、文字どおり変換を行わずOSで格納されているデータをそのまま送受信するモードである。そのほか「EBCDIC」と呼ばれるモードも用意されている。これは、IBM系汎用機で使用される文字コードであるEBCDICで送受信するモードだが、現在ではほとんど使用されることはない。「ローカルモード」と呼ばれる内部表現を送信側が規定するモードも定義されているが、これもほとんど使用されることはないだろう。ファイルの送受信あらかじめデータコネクションを作成しておけば、クライアントはサーバとの間でファイルの送受信が行えるようになる。ファイル名ファイルの受信を行うのがRETRコマンドだ。実行すると、データコネクションを通じて、指定したサーバ上のファイルの内容が取得できる。データコネクションでは当然のことながら、そのファイルの内容のみが送られてくるだけなので、FTPクライアントではその内容をもとにローカルディスクにファイルを作成する必要がある。STORコマンドは逆に、データコネクションを通じてサーバにファイル内容を送信する。送信した内容は、引数で指定した名前のファイルとして保存される。同じ名前のファイルが存在している場合には、上書き保存されることになる。FTPコマンド(CUI)でのgetやputコマンドは、内部でこれらのコマンドを使用している。述べたように、FTPにmgetやmputに該当する複数ファイルの送受信機能は存在していない。RETRやSTORを複数実行することで、機能を実現しているのだ。次回後編では、そのほかのコマンドやFTPの特別な機能について見てみよう。メールマガジンをご購読ください。Japanスマートジャパン3Dモデラボキャリア@IT自分戦略研究所エンジニアライフディルバートアプリITmediaねとらぼねこらぼついトピ!ITmediaはアイティメディア株式会社の登録商標です。