リモートプロシージャコールによる分散型アプリケーションの作り方がわかりたい

戻る

WindowsNTやWindows95は、ピアーツーピアー(peer to peer)の型と呼ばれる ネットワーク環境を提供しています。
これによりOSの利用者は、リモートマシンのクライアントとしてプリンタなど のリソースを共有し、またある時にはリモートマシンに対してリソースを提供する サーバとして動作します。
Windowsの場合、通常は1台のマシン上でアプリケーションを動作させますが、 ネットワーク上に処理能力の高いマシンがあれば、それを利用してアプリケーション を実行することができると便利です。
そこで、ここでは、Windows95, WindowsNT を利用して、リモートマシンに処理を 行わせる方法について考えてみましょう。

3-1 分散アプリケーション

○分散処理のメリットとWindows環境
UNIXマシンは、リモートマシンからTELENTで接続することにより利用できます。 これにより、必要に応じてリモートマシンのリソースを利用することができます (注1)。
(注1)WindowsNT4.0でもリソースキットで、TELNETデーモンのベータ版を提供している が、日本版のWindowsNT4.0で実行させると、動作が安定せず使い物にならなかった。
ある程度の規模のLAN環境では、サーバ専用のWindowsNTマシンやUNIXマシンが接続 され、一般的にそれらのマシンのほうがクライアントマシンより処理能力が高く、 複数のクライアントから利用するデータベースなどのリソースを管理しています。
各サーバーは、それぞれの処理を受け持っており、必要に応じてそれらのサーバー に対して処理を依頼します(図3-1)。
メインフレームのように全ての処理を1台のマシンで行うときと比べて1台のマシンの 負荷は小さくなり、本来処理を行うべきサーバがダウンしたとき、他のリモートマシン に処理を振り分けるといったことも現実的になります。
しかし、Windows環境ではそのような機能を標準機能として提供していません。


図3-1:分散処理

クライアント +----+ | | ユーザーインターフェース +----+ +--------+ +--------+ ↑ | | +-------------+-------------+ | | | | | | ↓ ↓ ↓ +--------+ +--------+ +--------+ | データ | | 計算 | | 計算 | | ベース | | 処理 | | 処理 | |サーバー| |サーバー| |サーバー| | | | 1 | | 2 | +--------+ +--------+ +--------+


○ローカルマシン内におけるプロセス間通信
WindowsではUNIXのようにリモートマシンのCPUを共有リソースとして利用する場面が あまりありません。OSがクライアントサーバーでなく、ピアーツーピアー指向のため かもしれませんが、WindowsNT5.0とWindows Terminal の出現で、WindowsNTマシンの CPUを共有することも増えてくるのではないかと思われます。
現状のWindowsNTリソースキットのように、RCMDのようにコンソール アプリケーションをリモートマシンで実行させるためのコマンドもありますが、 自分で作成するアプリケーションの一部をネットワーク上にある処理能力の高いマシン に行わせるためには、クライアントとサーバー共通の分散処理をサポートするための 基盤となる機能が必要となります。

○複数のマシン/異なるアーキテクチャのマシンにおけるプロセス間通信
複数のマシンにまたがって処理を行うときには、当然ウィンドウにメッセージを送る ことはできませんが、ソケットや名前付きパイプを利用して通信を行うことになるで しょう。
さらに、サーバに行わせる処理に関する情報をサーバに送信し、処理結果を受信する 仕掛けを作ることにより、より自然に処理を実行させることができるでしょう。
しかし、オープンシステム環境で構築されたLAN(ネットワーク)では、WindowsなどのPC 以外にUNIXマシンやメインフレームなども含まれることがあります。
また、小規模のオフィスで予算的にサーバ専用マシンを導入することが困難な環境 では、DOS+NetWare(+Windows3.1) や Windows95のようなOSをサーバにして、 クライアントとしても利用するといったことも考えられます。
このように、異なるアーキテクチャのマシン間で協調して動作したりお互いの リソースを提供するためには、共通の通信プロトコルや方式を採用する必要が あります。

3-2 DCEのRPC

○RPC(Remote Procedure Call)と何か
RPC(Remote Procedure Call)は、OSF(Open Software Foundation)によって1992年に 制定されたDCE(Desributed Computing Environment)と呼ばれる分散アプリケーション を作成するための規約の構成要素の一つです。
DCEのRPCは、当時の、Apollo社によって開発された Networking Conputing System から導入され、プロシジャ(関数)の処理をアプリケーション本体から分離して リモートマシンで実行させる機能を提供します。
アプリケーション本体は、分離された関数がどのように実行されるかを意識する必要が なく、ローカルの関数を呼び出すのと同様に呼び出す機能を提供するものです。

○インターフェース記述言語IDL(Interface Define Langurage)
RPCを利用するには、IDL(Interface Define Langurage)でリモートマシンで実行する 関数のインタフェースを定義します。IDLには、インタフェースの識別子である UUID(Universal Unique Identifer)や関数のプロトタイプを記述します。 UUID は、サーバが指定されたインタフェースを実行できるかを確認するための識別子 として利用させます。
このファイルをIDLコンパイラでコンパイルして、C言語のヘッダファイルと、スタブ と呼ばれるリモートマシンの関数を呼び出すための処理が記述されたC言語のソース ファイルを生成します。
呼び出す関数のプロトタイプ宣言は、生成されたヘッダファイルに設定されるため、 呼び出し側(クライアント)では通常の関数名を呼び出すの同様の記述で呼び出す ことができます。
IDLファイルは、UUIDGEN コマンドで生成することができます。UUIDGEN は、 インタフェースの識別子である UUID を生成ためのコマンドですが、-i パラメータを 指定することにより、IDLファイルの「ひな型」を生成することができます (例3-1, 例3-2)。
UUID は、OLEやCOMで利用する CLSIDIID と同一のため、 GUIDGEN で取得したGUID も同様に利用することができます(注2)。
(注2)CLSID, IID, GUIDGENは、第1章 1-4も参照



例3-1:UUIDを生成する
C:\>uuidgen 071ced00-4889-11d0-90fd-0040c757956e
例3-2:IDLを生成する
C:\>uuidgen -i [ uuid(071ced00-4889-11d0-90fd-0040c757956e), version(1.0) ] interface INTERFACENAME { }


○クライアントスタブとサーバースタブ
IDLファイルをIDLコンパイラでコンパイルすることで、クライアントスタブとサーバ スタブのソースファイルが生成されます。
クライアントスタブには、アプリケーション本体から呼び出されるサーバで実行される 関数を呼び出す処理が記述されます。
サーバスタブには、クライアントから要求のあったインタフェースの関数を呼び出し、 結果をクライアントに送り返す処理が記述されます。
クライアント・サーバ間の通信は、これらのスタブとRPCランタイムが自動的に行い、 指定された通信プロトコルを利用して通信を行います(図3-2)。

図3-2:RPCでの関数呼び出し

クライアント サーバー +--------------+ +-------------+ | 関数呼び出し | |呼び出される | | | | 関数本体 | | ↓ ↑ | | ↓ ↑ | +--------------+ +-------------+ | スタブ | ← IDLファイルから→ | スタブ | | ↓ ↑ | 生成されたスタブ | ↓ ↑ | +--------------+ +-------------+ |RPCランタイム | |RPCランタイム| | ↓ ↑ | | ↓ ↑ | +--------------+ +-------------+ |通信プロトコル| |通信プロトコル| +--------------+ +-------------+ | ↑ ネットワーク | ↑ | +----------------------------+ | +-------------------------------------------+


○サーバーの特定方法
クライアントがサーバーに関数の実行要求を行うとき、関数を実行するサーバーを特定 する必要があります。
サーバーの特定、つまりバインドを行うには、バインディングハンドルを識別子として 利用します。
このハンドルは、fopenFILE *fpのようなものですが、以降の処理は 全てこのハンドルを識別子として利用します。
このハンドルを取得するためのコードがどこにあるかによって、バインディング方法 は、手動バインディングと自動バインディングに分けられます。
  1. 手動バインディング:クライアントからサーバと接続点を直接指定することにより 特定する方法
  2. 自動バインディング:サーバがネームサービスにエクスポートしたバインド情報 を、クライアントが問い合わせて特定する方法
    リモートプロシジャを持つサーバは、ネームサービスにバインド情報をエクスポート します。
    クライアントは、リモートプロシジャを呼び出すために、ネームサービスに、 呼び出すリモートプロシジャに関する情報を問い合わせ、接続するサーバを特定 します(図3-3)。
    これにより、リモートプロシジャを提供するサーバが変更されても、 クライアントはその影響を受けることなくサービスを受けることができます。 ネームサービスのバインド情報を、インポート・エクスポートするには、 NSI(Name Service Independent) APIを利用することにより行えます。
NSP API は、処理によって異なりますが、以下のように関数名がRpcNsで 始まるAPIがこれに該当します。
RpcNsBindingImportBegin
RpcNsBindingImportDone
RpcNsBindingImportExport

○バインド情報が変更された場合への対処
クライアントまたはサーバのいずれかのバインド情報を変更により、もう一方がその 変更を意識させないようにする方法として、ACFファイル(属性構成ファイル)を 作成があります(例3-3)。
ACFファイルは、IDLコンパイラがスタブコードを生成するときに、バインディングを どのような方法で行うかを識別するために利用されるファイルです。
例3-3(a)の記述では、暗黙バインディングを行うことと、そのハンドルの指定 以外は何も行っていません。
サンプルプログラムでは、文字列でバインディング (RpcBindingFromStringBinding)を行っていますが、バインディングハンドルは ACFファイルに記述される「暗黙ハンドル」
handle_t hRemoteHandle
を利用することになります。
自動バインディングではハンドルを直接操作する必要がないため、ACFファイルは、 例3-3(b)となり、バインド処理をスタブコードに任せしまうことが できます。
手動バインディングでは、サーバーを独自に選択するため、本来処理すべきサーバー が利用できなくなったときに、他のサーバーに切り替えるといった処理が可能に なります。
そのため、バインディングハンドルの管理は、クライアントアプリケーションが行う 必要があります。
なお、ACFファイル中、
interface Remote
{
}
{}に囲まれる部分の記述は、インターフェースに含まれるプロシージャーに 対して、個別にバインディングハンドルの設定を行うときに記述します。


図3-3:ネームサービスでサービスを指定する

クライアント サーバー +------------+ +------------+ | | | | +→| | | |----+ | | | | | | | +------------+ +-----□-----+ | | | ↑ 端点 | | | | | | |(3)リモートプロシージャの呼び出し | | | +-----------------------------------+ (1)バインド情報の | エクスポート | | | ↓ | +------------+ +-------- (2)バインド情報のインポート ----------| ネーム | | サービス | | | +------------+


例3-3:ACFファイル
[ implicit_handle(handle_t hRemoteHandle) ] interface Remote { } (a)暗黙バインディング
[ auto_handle ] interface Remote { } (b)自動バインディング


3-3 Microsoft RPC

○拡張機能を持つMicrosoft RPC
Microsoft が提供するOSでも、RPCを利用することができます。
Microsoft RPC は、OSF/DCE で定義される RPC と互換性があり、相互に利用する ことができます。
Microsoft RPC には、OSF/DCE互換の機能以外に、独自の拡張機能を 持っています。ただし、Microsoft社製以外のOSとの間で RPC を利用するときには、 拡張機能を利用することができません。

○開発環境
Microsoft RPC の開発環境は、OSF/DCEのRPCとほとんど同様です(図3-4)。
RPCを利用するには、まずIDLファイルとACLファイルを作成します。IDLファイルは、 UUIDGEN で生成した「ひな形」に、インタフェースの記述を行います。
リモートプロシジャの定義は、C言語のプロトタイプ宣言とほとんど同様ですが、 引数が、入力値であるか[in]出力値[out]であるかまたはその両方 [in,out]であるかを明確に記述する必要があります。
RPCで利用する型は、基本的にC言語で利用できるものと同様ですが、OSや言語に よって多少の違いがあります。このため、OSF/DCEのRPCで定義されるデータ型を 利用する必要があります。
RPCでアドレスを渡すとき、実際にはアドレスが指すデータ のコピーを送信することになります。このため、指定するポインタの種類やデータの サイズを特定できるようにしなければなりません(表3-1, 表3-2)。
ポインタはできるだけ単純なものを選択しなければなりません。「単純なもの」とは、 必要最小限の機能を提供するポインタを指します。
参照ポインタの機能しか利用しないのに、フルポインタを指定したりすると、 ポインタ操作のためのコード(スタブやランタイムルーチンの処理)を実行するための、 オーバーヘッドが増大してしまいます。
また、[out]のポインタとしてしか利用しないポインタを[in,out]と 指定すると、送信したデータが送り返されるため、通信のオーバーヘッドも不必要に 増大してしまいます。
RPCでは、ポインタを渡したからといって、相手にポインタ値が渡されるのではなく、 ポインタが指す内容(データ)を相手に送信する必要があることに注意してください。
Microsoft のIDLコンパイラ MIDLの拡張機能を利用するには、MIDLコンパイラの オプションに /ms_ext を指定します。
Visual C++ ver4.2 付属の MIDL ver3.0 では、既定値オプションで拡張機能を利用 する設定になっています。
OSF/DCE 互換機能のみを利用するには、/osfオプションを設定します。 拡張機能には、COM(Component Object Model) のインタフェースを定義するために 利用する機能などが追加されています。


表3-1:ポインタの種類
ref参照ポインタ(参照データのポインタ)
uniqueユニークポインタ(NULLポインタを識別できる参照ポインタ)
ptrフルポインタ(複雑なデータ構造を扱える)
string'\0'で終わる文字列を指すポインタ

表3-2:RPCの基本データ
booleanTRUEまたはFALSEを指定する
byte8ビット
char符号なし8ビット
double64ビット浮動小数点
float32ビット浮動小数点
handle_tプリミティブハンドル
hyper64ビット整数
long32ビット整数
short16ビット整数
small8ビット整数
wchar_tワイドキャラクタ(/ms_extを指定時)




図3-4:分散アプリケーションの開発手順
UUIDGENで +------------------------+ UUIDを生成する ----→| RPCAPP.IDL | +------------------------+ +------------------------+ | RPCAPP.ACL | +------------------------+ | MIDLコンパイラ(MIDL.EXE) ↓ でコンパイルする +------------------------+ +------ | RPCAPP.H * | ------+ | +------------------------+ | | +------------------------+ | | | RPCAPP_S.C * | | | +------------------------+ | | +------------------------+ | | | RPCAPP_C.C * | | | +------------------------+ | ↓インクルード | ↓インクルード +------------------------+ | +-----------------------+ | SERVER.C | | | CLIENT.C | +------------------------+ | +-----------------------+ ↓コンパイル | ↓コンパイル +------------------------+ | +-----------------------+ | SERVER.OBJ | | | CLIENT.OBJ | +------------------------+ | +-----------------------+ | ↓コンパイル | | +------------------------+ | | +---| RPCAPP_S.OBJ | | | | +------------------------+ | | | +------------------------+ | | | | RPCAPP_C.OBJ |---+ | | | +------------------------+ | | | | | | ↓ ↓リンク ↓ ↓リンク +------------------------+ +-----------------------+ | SERVER.EXE | | CLIENT.EXE | +------------------------+ +-----------------------+ サーバー クライアント * MIDLコンパイラによって生成されるファイル

例3-4:インターフェースの宣言
long ServerProc([in,string] unsigned char *lpszClientName,[in] boolean fCallBack); (a)通常のプロシージャ [callback] void ClientProc([in,string] unsigned char *lpszServerName); (b)コールバックプロシージャ


○Microsoft RPC API
RPC関数は、関数名で用途が分かるようになっています。基本的に関数名は、
Rpc オブジェクト名 操作
の順番で記述されます。
これにより、関数名で関数の利用利用方法をある程度特定することができます。 UUIDの操作を行う関数には、Rpcが付きません。
OSF/DCE の RPC での関数名は
rpc_binding_free のように記述されますが、Microsoft RPC では、関数名の記述はRpcBindingFree のように先頭の1文字を大文字で下線は入れません。
OSF/DCE の RPC 用に記述されたソースファイルをコンパイル するときには、関数名以外に構造体名やエラーコードマクロの違いも含めて、 #defineなどを利用して独自に再定義する必要があります。
リモートプロシジャを実行するとき、注意しなければならないのは、実行パラメータ の送信・実行結果の受信に通信を利用していることです。 このため、リモートプロシジャが返却するエラー以外に、RPCランタイムが返却する エラーも取得する必要があります。
RPCランタイムでエラーが発生したときには、RPCランタイムは例外を発生させます。 リモートプロシジャを実行したときに例外が発生したときには、RPCランタイムからの エラーを取得する必要があります(例3-5)。

表3-3:操作するオブジェクトと関数
オブジェクト 関数名の識別子
バインディングハンドル RpcBindingRpcBindingFree
端点 RpcEpRpcEpRegister
インタフェース RpcIfRpcIfInqId
マネージメント RpcMgmtRpcMgmtStopServerListening
ネームサービス(グループエントリー) RpcNsGroupRpcNsGroupDelete
ネームサービス(マネージメント) RpcNsMgmtRpcNsMgmtEntryCreate
ネームサービス(プロファイルエントリー) RpcNsProfileRpcNsProfileEltAdd
ネームサービス(サービスエントリー) RpcNsBindingRpcNsBindingExport
ネットワーク RpcNetworkRpcNetworkInqProtseqs
オブジェクト RpcObjectRpcObjectSetType
プロトコルシーケンスベクター RpcProtseqVectorRpcProtseqVectorFree
サーバーRpcServer RpcServerListen
文字列RpcString RpcStringFree
文字列バインディング RpcStringBindingRpcStringBindingCompose
UUIDの操作 UuidUuidCreate



例3-5:リモートプロシージャの実行
RpcTryExcept{ ServerProc(szMachineName, fCallBack); /* リモートプロシジャの実行 */ } RpcExcept(1){ /* 異常終了した */ rsResult = RpcExceptionCode(); } RpcEndExcept;
図3-5:アプリケーションとRPCランタイムライブラリ間のRPC API
+------------------------------------------+ | アプリケーション | +------------------------------------------+ ↑ ↑ | | RPC_API | | | | | +------------------------+ | RPC_USER | スタブ | RPC_ENTRY | +------------------------+ | | ↑ | | | RPC_STUB RPC_ENTRY | | | ↓ ↓ +------------------------------------------+ | RPCランタイムライブラリ | +------------------------------------------+



○関数の型
RPCで利用されるAPIの型は、
__RPC_USER,
__RPC_API,
__RPC_STUB,
__RPC_ENTRY
で定義されます。これにより定義される関数がどのように利用されるかをある程度 知ることができます(図3-5, 表3-4, 例3-6)。 古いコンパイラでは特別な型を利用する必要があったのか、それとも将来の拡張用 か、または純粋に用途を区別することだけに定義されたのかはわかりませんが、 Visual C++ ver 4.x やWin32 API の RPC.HRPCBASE.H では全て __stdcall と定義されています。
16ビットアプリケーションでは、これらのマクロによって、API のポインタは全て FAR ポインタであることが保証されます。


表3-4:RPCで利用するAPIのマクロ
マクロ説明
__RPC_API スタブから呼び出されるユーザアプリケーション関数
__RPC_FAR ポインタの標準マクロ
__RPC_STUB RPCランタイムライブラリから呼び出されるスタブ関数
__RPC_USER RPCランタイムライブラリからユーザアプリケーション関数
__RPC_ENTRY ユーザアプリケーションまたはスタブから呼び出されるRPCランタイム関数



例3-6:ユーザーアプリケーションに定義する__RPC_USER関数
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); } void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) { HeapFree(GetProcessHeap(), 0, ptr); }


○文字列バインディング
RPCで利用する通信プロトコルと端点を定義するために、あらかじめ定義させた 文字列を指定します。利用できる通信プロトコルは実行するOSや動作環境によって 異なります。サーバーの指定方法も各プロトコルごとに異なります。
OSに通信プロトコルがインストールされていなければOS自身がサポートしてい ても利用することができません。
また、Windows95 は、ネームサービスをサポートして いないがないため、Windows95 をサーバとするときには自動バインディングを行うこと ができません。

○利用可能なプロトコルと設定(表3-5〜表3-7)
実行するマシンで現在利用可能なプロトコルは、レジストリに記録されます。
クライアントで利用できるプロトコルは
ClientProtocols
サーバで利用できるプロトコルは
ServerProtocols
に設定されます。
内部的には、ここに設定される値で動作していると思われますが、実際に利用できる プロトコルをこの値で確認することができます(図3-6)。 WindowsNT ではネームサービスの設定を行うことにより、自動バインディングを 行うことができます(図3-7)。
Windows95 では、ネームサービスをサポートしていませんが、ネットワークドメイン 内に WindowsNT があれば、そちらに処理まかせてしまうことができます。
これにより、RpcNs API を擬似的に動作させることができます (図3-8)。



表3-5:RPCで利用できるプロトコルとサポート
プロトコルクライアントサーバ
ncacn_nb_tcp
コネクション指向 NetBIOS オーバーTCP
MS-DOS, Windows 3.x,
WindowsNT
WindowsNT
ncacn_nb_ipx
コネクション指向 NetBIOS オーバーIPX
MS-DOS, Windows 3.x,
Windows95, WindowsNT
Windows95, WindowsNT
ncacn_nb_nb
コネクション指向 NetBEUI
MS-DOS, Windows 3.x,
Windows95, WindowsNT
Windows95, WindowsNT
ncacn_ip_tcp
コネクション指向 TCP/IP
MS-DOS, Windows 3.x,
Windows95, WindowsNT
Macintosh
Windows95, WindowsNT
ncacn_np
コネクション指向名前付きパイプ
MS-DOS, Windows 3.x,
Windows95, WindowsNT
Windows NT
ncacn_spx
コネクション指向 SPX
MS-DOS, Windows 3.x,
Windows95, WindowsNT
Windows95, WindowsNT
ncacn_dnet_nsp
コネクション指向 DECnet トランスポート
MS-DOS, Windows 3.x  
ncacn_at_dsp
AppleTalk DSP
Macintosh server WindowsNT
ncacn_vns_spp
コネクション指向 Vines SPP トランスポート
WindowsNT WindowsNT
ncadg_ip_udp
データグラム(コネクションレス) UDP/IP
MS-DOS, Windows 3.x,
WindowsNT
WindowsNT
ncadg_ipx
データグラム(コネクションレス) IPX
MS-DOS, Windows 3.x,
WindowsNT
WindowsNT
ncalrpc
ローカルプロシージャコール
Windows95, WindowsNT Windows95, WindowsNT

表3-6:プロトコルのネットワークアドレス
ncacn_nb_tcpマシン名
ncacn_nb_ipxマシン名
ncacn_nb_nbマシン名
ncacn_ip_tcp インターネットアドレス (xxx.xxx.xxx.xxx)
ncacn_npサーバ名
ncacn_sp IPX インターネットアドレスまたはサーバ名
ncacn_dnet_nsp エリア, ノードシンタックス
ncacn_at_dsp マシン名, マシン名@ゾーン名 (servername@zonename)
ncacn_vns_spp StreetTalkサーバ名 (item@group@organization)
ncadg_ip_udp インターネットアドレス
ncadg_ipx IPX インターネットアドレスまたはサーバ名
ncalrpcマシン名

表3-7:プロトコルと端点
ncacn_nb_tcp 0から255(0から32はMicrosoftが予約)
ncacn_nb_ipx 0から255(0から32はMicrosoftが予約)
ncacn_nb_nb 0から255(0から32はMicrosoftが予約)
ncacn_ip_tcp インターネットポート番号
ncacn_np 名前付きパイプ名(\\pipe\\paiename)
ncacn_sp 1から65535
ncacn_dnet_nsp DECnetフェーズIV オブジェクト番号 #nn
ncacn_at_dsp 22バイト以内の文字列
ncacn_vns_spp Vines SPP ポート番号 255から511
ncadg_ip_udp インターネットポート番号
ncadg_ipx 1から65535
ncalrpc アプリケーションまたはサーバー固有文字列




図3-6:レジストリによるRPCのプロトコルの確認
HKEY_LOCAL_MACHINE + \SOFTWARE + \Microsoft + \RPC + \ClientProtocols ←クライアントで利用できるプロトコル + \ServerProtocols ←サーバで利用できるプロトコル
図3-7:WindowsNTはネームサービスをサポートする
HKEY_LOCAL_MACHINE + \SOFTWARE + \Microsoft + \RPC + \NameService
図3-8:Windows95で擬似的にネームサービスを動作させる
HKEY_LOCAL_MACHINE + \SOFTWARE + \Microsoft + \RPC + \NameService DefaultSyntax REG_SZ = 3 EndPoint REG_SZ = \\pipe\\locator NetworkAddress REG_SZ = \\NTSERVER Protocol REG_SZ = ncacn_np ServerNetworkAddress REG_SZ = \\NTSERVER



3-4 プログラムについて

○サンプルソース \RPC
CLIENT.EXE(サンプルRPCクライアント)
SERVER.EXE(サンプルRPCサーバ)
REMOTE.C(サンプルアプリケーション本体、サーバー、クライアント共通)
REMOTE.H(サンプルアプリケーション本体ヘッダ)
RPCCLI.C(RPCクライアント処理)
RPCSVR.C(RPCサーバ処理)
GETSVR.C(サーバ名設定ダイアログボックス、サーバー)
RPCSTB.IDL(MIDLソースファイル)
RPCSTB.ACF(ACFファイル)
REMOTE.RC(リソース)
REMOTE.ICO(アイコン)
MAKEFILE(メイクファイル)

○使い方
Windows95, WindowsNT で動作するRPCクライアント/サーバーです。
Windows95 では、自動バインディングをサポートしていないため、手動バインディング でサーバを起動します。
クライアントでは、サーバを指定することができます。起動時には、
localhost
に設定されます。
この設定は、TCP/IP(UDP/IP) を利用するときのみローカルホストとして認識 されます。リモートマシンを設定するときには、あらかじめ HOSTSファイルに 設定されているホスト名でなければなりません。
クライアントはサーバーが持つプロシジャを実行し、実行されたプロシージャから、 クライアントのコールバック関数を呼び出すことができます。 プロシジャでは、処理らしいことをなにもしていませんので、ローカル関数を 呼び出したときと比較して、RPCのオーバヘッドのほうが大きくなっています。
プロシジャの処理時間を、ウィンドウにログとして表示しますので、プロシジャ内に RPCで行わせたい処理を追加することにより、簡単なベンチマークテストを行うことが できます。
通信に利用するプロトコルは、ncacn_ip_tcp (TCP/IP)で、ポート番号は 2025 を 利用しています。他のアプリケーションでこのポートを利用しているときは、サーバ 起動時にエラーが発生しますので、そのアプリケーションを終了させるか、 REMOTE.HSZENDPOINT を変更して、再コンパイルを行う必要が あります。