レベル: 中級 Karthik Subbian (ksubbian@in.ibm.com), Staff Software Engineer, IBM India Ramakrishnan Kannan (rkrishnan@in.ibm.com), Staff Software Engineer, IBM India
2006年 6月 20日 XML-RPC は、異種のプラットフォーム間で複合 XML ベースの通信を可能にする、軽量で単純かつ強力なメッセージング・プロトコルです。この記事では、C++ プログラムを対象とした独自の XML-RPC ベースのサービスを作成する方法について説明します。
はじめに
インターネットの普及が進む今日、インターネットならではの利点は、開発者やIT 部門が複合 C/C++ ビジネスと科学的アプリケーションを Web ベースの環境に統合する動機となっています。従来のアプリケーションを WWW に統合しやすくするものとして、SOAP (SimpleObject Access Protocol)、REST (Representational State Transfer)、そしてXML-RPC (XML リモート・プロシージャー・プロトコル) などの Web サービスがあります。このうちXML-RPC は、既存の C/C++ プログラムをクライアント・サイドのその他の技術に統合するメカニズムにもなります。この記事を読むと、どのような場合に SOAP や REST ではなく、XML-RPC を選択すればいいのかが分かるようになります。また、オープン・ソース XML-RPC ライブラリーを使用した C++ 統合についてのステップバイステップ・ガイドとサンプル・コードの抜粋も記載しています。
XML-RPCを使用する理由とは?
C/C++ コードを統合する際の課題は、さまざまな方法で解決されています。 従来のC/C++ コードの統合方法には、COBRA (Common Object Request Broker Architecture)、DCOM(Distributed Component Object Model)、RMI (Remote Method Invocation) IIOP(Internet Inter-ORB Protocol)、JNI (JavaTM native interface) などのインターフェースが使用されています。
図 1 に、従来の方法による既存の C++ コードと 3 つのアプリケーションの統合を示します。これらのアプリケーションはそれぞれ3 種類のプログラミング言語 (Java、VC++、PL/1) で開発されています。
図1. XML-RPC を使用しない現在のシナリオ
上の図から分かるように、C++ コードでは RMI/IIOP/JNI、CORBA および DCOMクライアント・サイドのそれぞれの統合技術ごとに、対応するインターフェースを公開する必要があります。つまり開発に 3 倍の労力を必要とし、複合インターフェースをデプロイして管理するプロセスが非常に困難で骨の折れるものとなってしまいます。
このような場合には、XML-RPC を選択するほうが賢明です。XML-RPC によって、開発、デプロイ、そして管理が簡単になるためです。
 |
XML-RPC および REST について
XML-RPC は、UserLand Software の Dave Winer によって 1998 年に考案されました。XML-RPCの着想については、Dave Winerのブログにアクセスしてください。
REST は当初、カリフォルニア大学アーヴィン校の Roy Thomas Fielding が博士号論文のなかで提案したものです。
|
|
図 2. XML-RPC を使用した場合
図 2 には、XML を使用したリモート・プロシージャー・コールで、HTTP を介してC++ プログラムを呼び出す場合を示しています。 SOAP や REST などの技術も、同じ役目を果たします。ただし次のセクションで説明するように、これらの技術には決定的な違いがあります。
SOAP、XML-RPC、RESTの比較
3 つのプロトコルはすべて HTTP を介した XML-RPC をサポートしますが、C++に関する違いがそれぞれにあります。 表 1 で、これらのプロトコルのエレメントを詳細に比較しています。
表 1. SOAP、XML-RPC、RESTの比較
| SOAP | XML-RPC | REST |
|---|
| 定義 | SOAP は、一元化されていない分散環境で情報を交換するための軽量なプロトコルです。これは XML ベースのプロトコルで、エンベロープ、エンコード規則のセット、そしてリモート・プロシージャー・コールとレスポンスに関する表記規則の3つの部分で構成されます。 | HTTP をトランスポートとして使用し、XML をエンコーディングとして使用するリモート・プロシージャー・コールです。XML-RPC は、複雑なデータ構造が送信され、処理され、そして返されることを可能にすると同時に、可能な限り単純であるように設計されています。 | REST は、適切に設計された Web アプリケーションの動作イメージを連想させることを目的としています。この動作イメージとは、つまり、ユーザーがリンクを選択してアプリケーション間を移動すると、ユーザーに次のページが転送され、使用方法に合わせてレンダリングされるといった、Webページのネットワークのことです。 | | 目標 | SOAP は、ユーザー定義のデータ型、宛先の指定機能、メッセージ固有の処理制御などの機能をインプリメントしてXML-RPC を拡張します。 | 明瞭かつ拡張可能で非常に単純なフォーマットです。 HTML コード作成者は、XML-RPCプロシージャー・コールが含まれるファイルを調べれば、その内容が理解できます。また、必要に応じてファイルを変更しても、1、2回の試行で XML-RPC プロシージャー・コールを成功させることができるはずです。インプリメントしやすいプロトコルなので、異なる環境や異種のオペレーティング・システムに簡単に適応させることができます。 | REST は、Web の動作に関する設計パターンを提供し、Web 標準および Web サービス設計の基本フレームワークとして役立つように作成されています。 | | サポートされるデータ型 | 整数、ブール値、ASCII 文字列、符号付倍精度浮動小数点数、日時、構造、配列、バイト配列、列挙、ユーザー定義データ型、多態的アクセサー | 整数、ブール値、ASCII 文字列、符号付倍精度浮動小数点数、日時、構造、配列 | インプリメンテーションによって異なります。 通常、整数、ブール値、ASCII文字列、符号付倍精度浮動小数点数、日時、セット、リスト、プロパティーがサポートされます。 | | 簡潔さ | XML-RPC に比べるとやや複雑です。 | 理解しやすく、開発も簡単です。 | インプリメンテーションによって異なります。 | | 安定性 | W3C 標準準拠 | 標準ではありません。 | アーキテクチャー参照。 標準は不要です。 | | インターオペラビリティー | REST/XML-RPC との相互運用はできません。 | REST/SOAP との相互運用はできません。 | SOAP/XML-RPC との相互運用はできません。 | | ツール | IBM および Microsoft をはじめとする多くの主要企業が、ツールで SOAP をサポートし始めています。 | ツールはまだ展開中です。 | 使用できるツールサポートは限られています。 | | カスタマイズ | 高度なカスタマイズが可能です。データ型およびプロトコルには依存しません。 | 軽量で、HTTP 上でのみ動作します。データ型のサポートは限られています。 | HTTP 上でのみ動作します。 | | ライブラリー | 多数のオープン・ソース・ライブラリーを使用できます。 | 多数のオープン・ソース・ライブラリーを使用できます。 以下のセクションで説明しています。 | 使用できるインプリメンテーション・ライブラリーは限られています。 |
表 2. C++ 向け各種 XML-RPC インプリメンテーション
| ライブラリーおよびパッケージ名 | 説明 |
|---|
|
PDEL
| PDEL (Packet Design Embedded Library) は、http_xml_send_xmlrpc メソッドとhttp_servlet_xmlrpc メソッドによるクライアントおよびサーバーの XML-RPCインプリメンテーションが含まれる C ライブラリーです。 これらの関数は、HTTPトランスポート・プロトコルでカスタム XML データを送信する際に役立ちます。このパッケージには、XML-RPC 以外の機能も多数含まれています。 | |
XMLRPC++
| XML-RPC 標準の C++ インプリメンテーションです。 単純なサーバーとクライアントが付属されています。オブジェクト指向テクノロジーを使用して、これらのサーバーおよびクライアント・クラスを継承し、ビジネス機能をサービスとして公開する独自のXML-RPC をインプリメントできます。 この記事のサンプル・インプリメンテーションと例では、このライブラリーを使用しています。 | |
XMLRPC-C
| メソッドをサービスとして公開するために C アプリケーションと C++ アプリケーションで使用できるC インプリメンテーションです。 このパッケージには、Abyss Web サーバーが含まれています。C++ メソッドを公開するには、C スタイル・ラッパーを必要な C++ メソッドに書き込み、そのメソッドをこのライブラリーを使用して公開します。 |
XML-RPC++ ライブラリーをインストールする
XML-RPC の C++ プログラムを使用可能にするには、まず、XML-RPC ライブラリー・インプリメンテーションをダウンロードしてインストールします。C++ プログラム用のさまざまなインプリメンテーションが用意されています。インプリメンテーションの詳細リンクは、参考文献にあります。
ここで紹介するサンプル・プログラムでは、XMPLRPC++ インプリメンテーションを使用します。このインプリメンテーションをダウンロードして Linux、AIX、32ビット Windowsなどのおなじみのプラットフォームにインストールする方法については、参考文献のセクションを参照してください。 サンプル・インプリメンテーションでは、RedHat 9 プラットフォームと XML-RPC++ 0.7 ライブラリーを使用します。
サンプル C++ アプリケーション
次のサンプル・アプリケーションは、ユーザー定義クラス「operations」を使用して2つの整数を加算する単純な演算です。 リスト 1 に、operations クラスのコードを抜粋します。
リスト 1. Operations
class operations {
public:
int add();
operations(int i, int j);
private:
int op1;//Operand 1
int op2;//Operand 2
};
|
このクラスのコンストラクターは 2 つの整数パラメーターを使用し、それぞれをop1 および op 2 プライベート変数に設定します。 リスト 2 に、このクラスのadd メソッドを示します。このメソッドを XML-RPC サービスとして公開します。
リスト 2. Operations.cpp
int operations::add()
{
std::cout << "Sum of "<<op1<<" + "<<op2<<" = "<<op1+op2<<std::endl;
return(op1 + op2);
}
|
XML-RPC ライブラリーのコンポーネント
このセクションでは、クラス図に XML-RPC ライブラリーに含まれるさまざまなコンポーネントを示し、これらのコンポーネントがサーバー・サイドのoperations クラスとどのようにインターフェースを取るかについて説明します。
図 3. XML-RPC ライブラリーとサンプル・アプリケーションのクラス図
表 3 に、それぞれのクラスの詳細を説明します。
表 3. クラスの詳細
| クラス名 | 目的 |
|---|
| Operations | このクラスで、公開対象の add メソッドをインプリメントします。 | | Add | operations クラスの add method() を呼び出すラッパークラスです。 また、このクラスはmyXmlRpcServerMethod を継承します。 | | myXmlRpcServerMethod | このクラスは、 XML-RPC ライブラリーの XmlRpcServerMethod クラスを継承します。このクラスの execute メソッドは、継承によって Add クラスでオーバーライドされます。 | | xmlRpcServermethod | サーバーに登録しなければならないすべてのメソッドは、myXmlRpcServerMethodクラスからこのクラスを継承して execute メソッドをインプリメントする必要があります。この execute メソッドが、実際に公開されるサービスのラッパーになります。サーバーが XML-RPC コールを受け取ると同時に、このラッパークラスの executeメソッドがトリガーされます。 この例では、Add がラッパークラスで、クライアント・サイドから「追加」サービスを起動すると、このクラスのexecute メソッドが呼び出されます。 | | myXmlRpcServer | このクラスには、以下の 2 つの重要なプライベート変数があります。
- pm_serverMethods: サーバーに登録されている myXmlRpcServerMethod へのポインターのリストです。
- pm_xmlRpcServer: サーバー IP、ポート、およびその他のプロパティーを設定します。
重要なメソッドには、次の3つがあります。
- クラス・コンストラクター: サーバー・オブジェクトを ip/port の詳細で初期化し、バインドします。
- pm_registerMethods: Add クラスへのポインター・オブジェクトを作成し、pm_serverMethodsリストにプッシュします。
- run: xmlRpcServer クラスの work メソッドのラッパーです。
| | xmlRpcServer | サーバー・オブジェクトを作成する XML-RPCサーバー・クラスです。 このクラスには、以下の2 つの重要なメソッドがあります。
- bindAndListen(port): 特定のポートをバインドしてリッスンします。
- work(...): サーバーを始動します。
|
リスト 3 に、上記のテーブルに記載した各クラスの .cpp ファイルごとのコードを示します。xmlRpcServer と xmlRpcServerMethod は XML-RPC ライブラリーにインプリメントされているため、残りの4 つのクラスに焦点を絞ります。
リスト 3. myXmlRpcServer.cpp
#include "myXmlRpcServer.h"
using namespace XmlRpc;
using namespace std;
myXmlRpcServer::myXmlRpcServer()
{
//call register methods
pm_registerMethods();
//set port bind and listen
int port = 8085;
pm_xmlRpcServer.bindAndListen(port);
std::cout<<"XmlRpcSever running in port "<<port<<std::endl;
}
void
myXmlRpcServer::pm_registerMethods()
{
Add* a=new Add(&pm_xmlRpcServer);
myXmlRpcServerMethod *p=a;
pm_serverMethods.push_back(p);
}
void
myXmlRpcServer::run()
{
pm_xmlRpcServer.work(-1);
}
|
リスト 4. myXmlRpcServer.h
#include <iostream>
#include "myXmlRpcServerMethods.h"
#include "XmlRpc.h"
class myXmlRpcServer {
public:
myXmlRpcServer();
void run();
private:
void pm_registerMethods();
XmlRpc::XmlRpcServer pm_xmlRpcServer;
std::list< myXmlRpcServerMethod* > pm_serverMethods;
};
|
リスト 5 とリスト 6 に、XmlRpc サーバーにメソッドを登録するために使用するクラスのコードを示します。このサーバーは、XML-RPCライブラリーに付属しています。
リスト 5. myXmlRpcServerMethods.cpp
#include <iostream>
#include "myXmlRpcServer.h"
#include "operations.h"
using namespace std;
Add::Add(XmlRpcServer* s) : myXmlRpcServerMethod("Add", s) {};
Void Add::execute(XmlRpcValue & params, XmlRpcValue& result)
{
operations a(10,12);
try
{
cout << "Inside Add::execute method\n";
result = a.add();
}
catch(std::exception & stde)
{
throw XmlRpcException(stde.what());
}
}
|
リスト 6. myXmlRpcServerMethods.h
class myXmlRpcServerMethod : public XmlRpcServerMethod
{
public:
myXmlRpcServerMethod
(const char *name, XmlRpcServer * server):XmlRpcServerMethod(name, server) {}
virtual void execute(XmlRpcValue & params, XmlRpcValue& result) {assert(0);}
};
class Add:public myXmlRpcServerMethod
{
public:
Add(XmlRpcServer* s);
virtual void execute(XmlRpcValue & params, XmlRpcValue& result);
};
|
サーバー・ドライバー
サーバー・サイドのエントリー・ポイントには、サーバー・ドライバー・プログラムを使用します。ここで myXmlRpcServer オブジェクトをインスタンス化して run() メソッドを呼び出すと、サーバーが始動します。
リスト 7. myServerDriver.cpp
#include <iostream>
#include "myXmlRpcServer.h"
int main(int argc, char* argv[])
{
myXmlRpcServer GeeBoomBaa;
std::cout<<"About to run the server\n";
GeeBoomBaa.run();
return 0;
}
|
サーバーを始動する
コードをコンパイルするには、(XML_RPC_INSTALL_DIR)/src と (XML_RPC_INSTALL_DIR)/includeディレクトリーを組み込まなければなりません。 リンク用には、libXmlRpc.aライブラリーを組み込みます。 コードが正常にコンパイルされてリンクされると、実行可能プログラムになります。これが、XML-RPCサーバーです。 以下のサンプル・インプリメンテーションでは、サーバーは localhostで実行され、ポート 8085 をリッスンします。これは、myXmlRpcServer.cpp ファイルにハードコーディングされます。ハードコーディングする代わりに、構成ファイルを読み込む方法や、コマンド・プロンプトからパラメーターとして渡す方法にすることもできます。正常にコンパイルおよびリンクされたら、完成した a.out プログラムを実行してサーバーを始動します。
サンプル・クライアント
サンプル・クライアントは、XML-RPC ライブラリーに提供されている XmlRpcClientクラスのオブジェクトをインスタンス化します。 このクラスの「execute(...)」メソッドは、以下の3 つのパラメーターを使用します。
- const char*: メソッド名
- const int: ポート番号
- オプションの uri 文字列: http get のヘッダー内の URI として送信されます。
リスト 8 に示すサンプル・クライアントは、「add(...)」メソッドを実行して、クライアント・サイドに結果を印刷します。
リスト 8. sampleClient.cpp
#include <iostream>
#include "XmlRpc.h"
using namespace XmlRpc;
int main(int argc, char* argv[])
{
const char *server = "localhost";
const int port = 8085;
const char *uri = NULL;
XmlRpcValue args, res;
XmlRpcClient c( server, port, uri);
c.execute("Add", args, res);
std::cout<<"result is "<<res<<std::endl;
}
|
まとめ
XML-RPC は、異種プラットフォーム間で複合 XML ベースの通信を可能にする、軽量で単純かつ強力なメッセージング・プロトコルです。この標準ならではの単純さは、従来のアプリケーションを企業向けアプリケーションに統合する際にその効果を発揮します。さまざまなインプリメンテーションを揃えた XML-RPC は、そのオープン・ソースの性質上、より多くのエンタープライズ・アプリケーション統合で活用されるようになっています。XML-RPC向けの一層高度なツールが登場するにつれ、この技術は企業内統合の「デファクト」スタンダードになることでしょう。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Karthik Subbian は現在、バンガロールの IBM India Software Laboratory でメーカー用の最適化製品のビルドに従事しています。また、クライアントのアプリケーション管理支援および IBM プラットフォームへのマイグレーション支援にも実績があります。ソフトウェア分野では、グリッド・コンピューティング、XML、Web サービス、そして SOA の分野を専門としています。 共著として、グリッド・コンピューティング・テクノロジーについての IBM Redbook があります。 彼は IBM 公認 XML ソリューション開発者、Sun 公認 Java プログラマーです。
|
 | 
|  | Ramakrishnan Kannan は、バンガロールの IBM India Software Laboratory でホスト統合に従事しています。彼は、IBM パーソナル・コミュニケーションズ製品と通信サーバー製品の開発者として活躍してきました。開発事業の他、IBM アジア・パシフィック地域のカスタマーと協力して、ホスト・アプリケーションのWeb サービス対応化にも取り組んでいます。 また、Developerworks のため、Infosys などのビジネス・パートナーとの Web サービス認識セッションを実施してきました。彼は IBM 公認 XML ソリューション開発者、Sun 公認 Java プロフェッショナルです。ホスト統合、分散コンピューティング、SOA、そしてネットワーキングを専門としています。
|
記事の評価
|