Boost」など、さまざまなカンファレンスを企画・運営しています。BOOKS(コードジン・ブックス)は、CodeZineの連載からカットアップした、開発現場の課題解決に役立つ書籍シリーズです。最後に参考資料ソース解説まずは、ソースの上から順に見ていきましょう。インクルード・ファイルインクルードするファイルは次のようになります。"Poco/File.h"Foundation、Util、Netコンポーネントを利用します。Foundationコンポーネントのインクルードファイルは、POCOディレクトリ直下にありますので、"Poco/Foundation/File.h"ではなく、"Poco/File.h"となります。名前空間もFoundationは定義されておらず、Poco::Fileのように書き、Foundationは不要です。次の行からはクラスの定義と実装になりますが、個々のクラスは後回しにして、プログラム本体の処理を見てみましょう。最後の部分がメイン処理です。argv);}MiniWebServerクラスがメインのアプリケーションクラスです。ここでは、そのクラスをインスタンス化し、run関数をコールして実行しているだけです。すべての処理は、MiniWebServerクラスに記述されています。アプリケーションクラスMiniWebServerクラスの定義と実装を見てみましょう。}};MiniWebServerクラスの1つ上の親クラスはPoco::Util::ServerApplicationクラスで、その親は、Poco::Util::Applicationクラスです。通常のアプリケーションでは、Poco::Util::Applicationクラスを継承して、初期化、実行、および終了処理をオーバーライドしたクラスを実装することになります。Poco::Util::ServerApplicationクラスは、アプリケーションをサーバとして利用する場合に便利な機能が追加されています。今回のアプリケーションは、サーバとして機能させるので、Poco::Util::ServerApplicationクラスを継承しています。最低限オーバライドすべき関数は、メインの実行処理を記述するmain関数です。main関数は、protectedになっているように、外部のクラスからは直接呼ぶことはできません。最初の_tmain関数のところで書いたように、アプリケーションの実行は、公開関数であるrun関数をコールすることで実行します。Applicationクラスのrun関数内部で、main関数がコールされています。main関数の例外を補足した場合のロギング処理などがカプセル化されています。今回は、最小限の機能しか実装しませんので、main関数のみオーバーライドします。main関数と同様にオーバライドすべき関数には、初期化処理を記述するinitialize()、解放処理を記述するuninitialize()があります。HTTPServerクラスmain関数では、Poco::Net::HTTPServerクラスをインスタンス化しています。HTTPServerクラスは、Webサーバのほとんどの機能をカプセル化しており、追加する処理は少なくてすみます。ここでは、HTTPServerクラスのインスタンスを生成した後、開始、終了待ち、終了処理の関数をコールしているだけです。Poco::Net::ServerSocketクラスはソケットのクラスで、Poco::Net::HTTPServerParamsクラスは、HTTPServerオブジェクトの設定値用データクラスです。今回のサーバは、クライアントもローカルの1接続と想定して、クライアント最大同時接続数を1にしています。この値を増やせば、通常のWebサーバのように、複数クライアントの処理も可能です。リクエストハンドラ・ファクトリHTTPServerクラスのコンストラクタに、引数としてMiniRequestHandlerFactoryクラスのオブジェクトを渡しています。名前から想像できるように、デザインパターンのFactoryMethodパターンの構造になっています。}};MiniRequestHandlerFactoryクラスの親クラスは、Poco::Net::HTTPRequestHandlerFactoryクラスで、HTTPのリクエストハンドラ生成を一手に処理しています。HTTPリクエストハンドラとは、WebブラウザなどのHTTPクライアントからのリクエストに対して、サーバとしての処理を実装しているオブジェクトです。MiniRequestHandlerFactoryクラスでは、FileRequestHandlerクラスとNotFileHandlerクラスの二つのハンドラオブジェクトを生成しています。クライアントからリクエストされたURIをそのまま要求されたHTMLファイル名とみなし、カレントディレクトリに、そのファイルがあるかどうかを判定しています。ファイルがあれば、FileRequestHandlerクラスのインスタンスを生成、なければ、NotFileHandlerクラスのインスタンスを生成します。リクエストハンドラすべてのリクエストハンドラは、Poco::Net::HTTPRequestHandlerクラスから継承します。実装しないといけない処理は、HTTPレスポンスコードと応答メッセージの設定です。handleRequest関数をオーバーライドして記述します。FileRequestHandlerクラスでは要求されたファイルをオープンして、response.sendFile関数でその中身をそのままレスポンス文字列に設定しています。ファイル内容は、まったくチェックしていません。乱暴ですので、実際の使用時には適宜エラー処理を追加してください。正常応答の場合は、HTTPレスポンスコードの設定は不要です。}};もう1つのNotFileHandlerクラスは、エラーレスポンスです。おなじみの「要求されたファイルが見つからない」というエラーの処理です。ここではレスポンスの文字列を直接プログラムで記述しています。FileRequestHandlerクラスと同様に、ファイルを読み込む方法でもかまいせん。実際にアプリケーションに組み込んで利用する場合は、適宜リクエストハンドラを追加することになります。本記事では単にファイルを返す処理しか実装していませんが、いくらでも自由に動的な処理を追加できます。指定しないでビルドすると、POCOのインポートライブラリがリンクされ、実行時にDLLファイルを利用する形になります。Foundation、Util、Net、XMLの4つのコンポーネントすべて使用しますので、DLLファイルのパスを通すか、実行ファイルと同じフォルダにコピーしておきましょう。1つ、実行する前に、あらかじめ動作確認用の適当なHTMLファイル(例えばindex.html)を作っておいてください。そのHTMLファイルを実行ファイルと同じところにコピーして、サーバを実行します。クライアントのブラウザを起動して、「http://localhost:9980/index.html」と入力してみてください。HTMLファイルが表示されるはずです。最後にPOCOを使えば、この程度のコード量でWebサーバを動作させることができます。IISやApacheなどの本格的なWebサーバにはかないませんが、アプリケーションに組み込みたい場合や、ローカル用にWebサーバが使いたい場合などで、重宝すると思います。今回紹介した以外にも、実用的なクラスが数多く揃っています。「車輪の再発明」をしないためにも、POCOの利用を一度検討してみてはいかがでしょうか。NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Technologies。執筆コミュニティ「WINGSプロジェクト」代表。