XML-RPC で C++ アプリケーションを Web サービス対応可能にする

C++ メソッドをサービスとして公開するためのステップバイステップ・ガイド

XML-RPC は、異種のプラットフォーム間で複合 XML ベースの通信を可能にする、軽量で単純かつ強力なメッセージング・プロトコルです。この記事では、C++ プログラムを対象とした独自の XML-RPC ベースのサービスを作成する方法について説明します。

Karthik Subbian (ksubbian@in.ibm.com), Staff Software Engineer, IBM India

Karthik SubbianKarthik Subbian は現在、バンガロールの IBM India Software Laboratory でメーカー用の最適化製品のビルドに従事しています。また、クライアントのアプリケーション管理支援および IBM プラットフォームへのマイグレーション支援にも実績があります。ソフトウェア分野では、グリッド・コンピューティング、XML、Web サービス、そして SOA の分野を専門としています。 共著として、グリッド・コンピューティング・テクノロジーについての IBM Redbook があります。 彼は IBM 公認 XML ソリューション開発者、Sun 公認 Java プログラマーです。



Ramakrishnan Kannan (rkrishnan@in.ibm.com), Staff Software Engineer, IBM India

Ramakrishnan KannanRamakrishnan Kannan は、バンガロールの IBM India Software Laboratory でホスト統合に従事しています。彼は、IBM パーソナル・コミュニケーションズ製品と通信サーバー製品の開発者として活躍してきました。開発事業の他、IBM アジア・パシフィック地域のカスタマーと協力して、ホスト・アプリケーションのWeb サービス対応化にも取り組んでいます。 また、Developerworks のため、Infosys などのビジネス・パートナーとの Web サービス認識セッションを実施してきました。彼は IBM 公認 XML ソリューション開発者、Sun 公認 Java プロフェッショナルです。ホスト統合、分散コンピューティング、SOA、そしてネットワーキングを専門としています。



2006年 6月 20日

はじめに

インターネットの普及が進む今日、インターネットならではの利点は、開発者や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 を使用しない現在のシナリオ
図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-RPC を使用した場合

図 2 には、XML を使用したリモート・プロシージャー・コールで、HTTP を介してC++ プログラムを呼び出す場合を示しています。 SOAP や REST などの技術も、同じ役目を果たします。ただし次のセクションで説明するように、これらの技術には決定的な違いがあります。


SOAP、XML-RPC、RESTの比較

3 つのプロトコルはすべて HTTP を介した XML-RPC をサポートしますが、C++に関する違いがそれぞれにあります。 表 1 で、これらのプロトコルのエレメントを詳細に比較しています。

表 1. SOAP、XML-RPC、RESTの比較
SOAPXML-RPCREST
定義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 インプリメンテーション
ライブラリーおよびパッケージ名説明
PDELPDEL (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 クラスのコードを抜粋します。

ご存知ですか?

Eclipse を IDE として使用して、C/CPP アプリケーションを開発できます。 詳細については、Eclipse CDT にアクセスしてください。

リスト 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. XML-RPC ライブラリーとサンプル・アプリケーションのクラス図

表 3 に、それぞれのクラスの詳細を説明します。

表 3. クラスの詳細

クラス名目的
Operationsこのクラスで、公開対象の add メソッドをインプリメントします。
Addoperations クラスの add method() を呼び出すラッパークラスです。 また、このクラスはmyXmlRpcServerMethod を継承します。
myXmlRpcServerMethodこのクラスは、 XML-RPC ライブラリーの XmlRpcServerMethod クラスを継承します。このクラスの execute メソッドは、継承によって Add クラスでオーバーライドされます。
xmlRpcServermethodサーバーに登録しなければならないすべてのメソッドは、myXmlRpcServerMethodクラスからこのクラスを継承して execute メソッドをインプリメントする必要があります。この execute メソッドが、実際に公開されるサービスのラッパーになります。サーバーが XML-RPC コールを受け取ると同時に、このラッパークラスの executeメソッドがトリガーされます。 この例では、Add がラッパークラスで、クライアント・サイドから「追加」サービスを起動すると、このクラスのexecute メソッドが呼び出されます。
myXmlRpcServerこのクラスには、以下の 2 つの重要なプライベート変数があります。
  1. pm_serverMethods: サーバーに登録されている myXmlRpcServerMethod へのポインターのリストです。
  2. pm_xmlRpcServer: サーバー IP、ポート、およびその他のプロパティーを設定します。

重要なメソッドには、次の3つがあります。
  1. クラス・コンストラクター: サーバー・オブジェクトを ip/port の詳細で初期化し、バインドします。
  2. pm_registerMethods: Add クラスへのポインター・オブジェクトを作成し、pm_serverMethodsリストにプッシュします。
  3. run: xmlRpcServer クラスの work メソッドのラッパーです。
xmlRpcServerサーバー・オブジェクトを作成する XML-RPCサーバー・クラスです。 このクラスには、以下の2 つの重要なメソッドがあります。
  1. bindAndListen(port): 特定のポートをバインドしてリッスンします。
  2. 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 つのパラメーターを使用します。

  1. const char*: メソッド名
  2. const int: ポート番号
  3. オプションの 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向けの一層高度なツールが登場するにつれ、この技術は企業内統合の「デファクト」スタンダードになることでしょう。

参考文献

学ぶために

製品や技術を入手するために

  • Sourceforge.net から、XMLRPC++ をダウンロードしてインストールできます。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=SOA and web services, XML
ArticleID=245554
ArticleTitle=XML-RPC で C++ アプリケーションを Web サービス対応可能にする
publish-date=06202006