ACE Tutorial 001
初心者のための ACE ツールキットガイド


このチュートリアルの目的は、複数のクライアントからのコネクションを処理できるとても単純なサーバの例を示すことにある。 "伝統的な"サーバアプリケーションとは異なり、全てのリクエストを単一プロセスで処理する。 マルチプロセッシングやマルチスレッディングについては後の章で取り扱う。


さて、あなたはサーバを作るのに何が必要だと思うか?

  1. クライアントからの接続を受け付ける何か
  2. 無事に接続されたコネクションを取り扱うための何か
  3. これらを扱うメインループ

ACE の acceptor が一つ目の問題を解決する。 このクラスは TCP/IP のポート番号をもらって、そのポートで接続を待ち受ける。 コネクションの依頼が届くと acceptor はそれを処理するためのオブジェクト(ハンドラ)を作成し、そいつにクライアントとのコネクションを任せて、自分はまた新規の接続待ちに戻る。

そして ACE EventHandler が二つ目の要求を満たす。 ここでは詳しく説明しないが、チュートリアルを進めていくにつれて、この役割が明確になっていくだろう。

最後に単純な main() 関数がプログラムのメインループとして用意できる。 プログラムの初期化処理が終わると、後はずっと acceptor の接続か EventHandler のデータイベントを待つための無限ループに入る。


さて、続きをやる前にもう一つの ACE のコンセプトである Reactor について紹介をしよう。

ここでは Reactor が一体何をするかという詳細にまでは立ち入らず、それが何でどう動くかだけ説明する。 これは紹介していくコード中の最初の一片を理解するために必要なことである。 次の図は Reactor と Acceptor とハンドラの関係を示すものである。

概要:
Reactor は他のオブジェクトからの物事に反応するオブジェクトである。 これらの(他のオブジェクトから来る)物事を「イベント」と呼ぶ。 リアクタ以外のオブジェクトはリアクタに対して「登録」されたオブジェクト群とやりとりを行う。 その登録の際には、どのようなイベントに反応するかを設定することもできる。 リアクタは、登録されたオブジェクトに(設定した種類の)イベントが起こると、OSから通知を受ける。 そうするとリアクタはそのイベントを処理するために、登録されたオブジェクトのメンバ関数を呼び出す。 このとき、リアクタ自身はどういうイベントが起きたかを関知しない。 イベントを正しく処理するのは、メンバ関数の呼び出しを受けたオブジェクトの責任である。 リアクタはオブジェクトにイベント発生を通知するだけの存在だ。

なぜリアクタを使うのか?

これはチュートリアルを進めていくうちにハッキリする。 今の時点では簡単に「単一スレッドのサーバで複数クライアントの接続を効率的に処理するため」と言っておこう。

サーバは伝統的には各クライアントについて別スレッドやプロセスを作成して対処していた。 これは(telnetやftpのような)大規模なサービスについては適切な方法である。 しかし、小規模サービスにおいては処理内容よりもプロセス生成の方がオーバーヘッドになる。 そのため、クライアント毎のプロセス生成の代わりにスレッドが使われるようになった。 大半の場合はこれでうまくいくのだが、いくつかのケースではやはりオーバーヘッドになることがあった。 では単一スレッドで、スレッドorプロセス パー クライアントよりも賢い負荷分散の方法は無いのだろうか? リクエストの処理が即座に行えるほど軽い場合には、全てのリクエストを1スレッド1プロセスで応対するのが唯一の解である。

これらが Reactor の柔軟性と威力を示す根拠である。 開発者はこの単純な1スレッドアプリケーションを、後からスレッドパークライアントやプロセスパークライアント、スレッドプール方式などに変更することができる。

ここまでを見て ACE は取り扱いが難しいのではないかと考えているとしても心配はいらない。 これから徐々に詳細についての説明をしていく。 分からない部分は、とりあえずそんなことが書いてあったと頭の片隅に置いておき、後から読み返してもらえばいい。


[インデックスへ] [続きに進む]