ONC+ 開発ガイド

プロトコルの概要

RPC プロトコルには、以下の機能があります。

ネットワーク・ファイル・サービスが 2 つのプログラムで構成されていると考えてください。1 つのプログラムは、ファイルシステムへのアクセス制御やロックなど高レベルのアプリケーションを扱います。もう 1 つのプログラムは、低いレベルの入出力ファイルを扱い、「読込み」や「書込み」などの手続があります。ネットワークファイルサービスのクライアントマシンは、クライアントマシンのユーザーのために 2 つのプログラムに関連する手続きを呼び出します。クライアントサーバーモデルでは、遠隔手続き呼び出しは、サービスを呼び出す場合に使用します。

RPC モデル

RPC モデルは、ローカル手続き呼び出しモデルに似ています。ローカル手続き呼び出しでは、呼び出し側が手続きへの引数を特定の記憶領域に書き込みます。次に呼び出し側が制御を手続きに渡しますが、最終的には再び制御が呼び出し側に戻ります。その時点で手続きからの戻り値は特定の記憶領域から取り出され、呼び出し側は処理を続行します。

RPC もこれと同様に実行されますが、1 つの制御スレッドが論理的に 2 つのプロセスにまたがって実行されます。2 つのプロセスとは、呼び出し側のプロセスとサーバープロセスです。概念的には、呼び出し側のプロセスがサーバープロセスに呼び出しメッセージを送り、その後応答メッセージが返されるまで待ちます (ブロックします)。呼び出しメッセージには、さまざまなデータとともに手続きへの引数が含まれています。応答メッセージには、さまざまなデータとともに手続きからの戻り値が含まれています。応答メッセージを受信すると、その中から戻り値が取り出され、呼び出し側の処理が再開します。

サーバー側では、プロセスは呼び出しメッセージが到着するまで休止しています。呼び出しメッセージが到着すると、サーバープロセスはその中から手続きへの引数を取り出し、戻り値を計算し、応答メッセージを送信して、次の呼び出しメッセージが来るのを待ちます。

この説明では、2 つのプロセスのうち同時にはどちらか一方だけがアクティブになることに注意してください。ただし、これ以外の呼び出し方法も可能です。RPC プロトコルでは、同時実行モデルも使用できます。たとえば、RPC 呼び出しを非同期モードで実行すれば、クライアントはサーバーからの応答を待つ間も作業を続けることができます。また、サーバーでは、到着した要求を処理するために新たなタスクを生成して、別の要求の受信も続けることができます。

トランスポートとセマンティクス

RPC プロトコルとトランスポートプロトコルとは互いに独立しています。すなわち、RPC では、メッセージがプロセス間で実際にどのように伝送されるかについては関知しません。RPC プロトコルで対象にしているのは、メッセージの仕様と解釈方法だけです。

RPC では、トランスポートの信頼性を保証していません。ですから、RPC で使用されるトランスポートプロトコルの型についての情報をアプリケーションに指定する必要があります。もし、RPC サービスが TCP のような信頼性の高いトランスポートを使用しているとわかっていれば、必要な作業はほとんどトランスポートで実行されています。反対に、RPC が UDP のような信頼性の低いトランスポート上で実行されている場合は、サービスの方で再転送やタイムアウトに対する処理を行わなければなりません。RPC ではそのようなサービスを提供しません。

RPC はトランスポート独立であるため、RPC プロトコルは、遠隔手続きやその実行に特定のセマンティクスを結び付けることができません。セマンティクスは、使用しているトランスポートプロトコルから推測されます。ただし、明示的に指定されなければなりません。たとえば、RPC が信頼性の低いトランスポート上で実行されている場合を考えてみます。アプリケーションが短時間のタイムアウト後に RPC メッセージを再転送する場合、応答が返されなければ手続きが 0 回以上実行されたことしか推測できません。応答が返された場合は、手続きが少なくとも一度は実行されたことが推測できます。

サーバーでは、一度だけ実行というセマンティクスをある程度実現するため、以前にクライアントから受け取った要求を記憶しておいて、同じ要求を再受信しないようにする場合があります。その場合サーバーは、RPC 要求に必ず含まれているトランザクション ID を利用します。トランザクション ID は、主として RPC クライアントが、応答と要求との対応を調べるために使用します。クライアントアプリケーションでは、要求を再送信するときに以前のトランザクション ID を再使用することができます。サーバーアプリケーションでもこのことを確認していれば、要求を受信したときはトランザクション ID を記憶しておいて、同じ ID を持つ要求は再受信しないことができます。サーバーでは、以前と同じ要求かどうか調べるため以外の目的でトランザクション ID を使用することはできません。

反対に TCP のような信頼性の高いトランスポートを使用している場合、応答メッセージが返されればアプリケーションは手続きが一度だけ実行されたと推測できます。ところが、応答メッセージが返されないからといって、遠隔手続きが一度も実行されなかったと推測することはできません。TCP のような接続型プロトコルを使用する場合も、サーバーのクラッシュに対応するために、アプリケーションでタイムアウトと再接続確立の操作が必要なことに注意してください。

結合と相互認識の独立性

クライアントとサービスの結合は、遠隔手続き呼び出しの仕様の一部ではありません。結合という重要で不可欠な機能は、より上位レベルのソフトウェアで行います。そのソフトウェアでも RPC を使用することがあります。rpcbind プロトコル」の節を参照してください。

そのようなソフトウェアを開発する場合は、RPC プロトコルをネットワーク間のジャンプ - サブルーチン命令 (JSR 命令) と考えます。ローダー (バインダ) は、JSR 命令を実行可能にするために、ローダー自身も JSR 命令を使用します。同様に、ネットワークは RPC を実行可能にするためにネットワーク自身も RPC を使用します。

RPC プロトコルには、サービスに対してクライアントが自分自身を証明するため、またはその反対方向の証明のためのフィールドが用意されています。セキュリティやアクセス制御の機能は、メッセージ認証の上に成り立っており、何種類かの認証プロトコルをサポートできます。どのプロトコルを使用するかは、RPC ヘッダーの 1 フィールドで指定します。認証プロトコルについての詳細は、「レコードマーク標準」の節を参照してください。