SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

ASP.NETでCometを利用したチャットを実装する

Webブラウザのみで行えるリアルタイムチャットアプリケーション(ASP.NET版)


  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード ソースコード (21.3 KB)

前稿では、JavaでCometとAjaxを利用し、Webブラウザ上で動作するWebチャットを実装しました。今回はそれをASP.NET上で実現する方法を説明します。ASP.NETの非同期HTTPハンドラを利用すると、それだけで単純なCometの実装ができます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 本記事では、『CometとAjaxを利用したチャットサーバの実装』で紹介したCometを利用したWebチャットを、ASP.NET上で実現する方法を説明します。CometというWebアプリケーションのアーキテクチャや、クライアントとサーバーの動作については、前掲の記事を参照してください。

対象読者

 本記事は中級以上のWebアプリケーション開発者を対象に、ASP.NETの非同期ハンドラのデザインを説明します。本記事の関心の対象は、ASP.NETの非同期ハンドラというデザインパターンのため、対象読者を必ずしもASP.NETを対象として開発されている方に限定していません。

 ただし、開発環境としてWindows XPまたはWindows 2003 Serverと、Visual Studio 2005またはVisual Web Developer 2005 Express Editionの利用を前提とするため、実際にサンプルを動作させるにはこれらが必要となります。また、言語にはC#を利用します。

 なお、本記事では『CometとAjaxを利用したチャットサーバの実装』で利用したクライアント側コードの一部を流用しています。この中で利用しているprototype.jsを利用している個所については説明を省略します。必要であれば前掲記事を参照してください。

必要な環境

 本記事のサンプルを実行するには、Visual Studio 2005またはVisual Web Developer 2005 Express Editionと、これらを実行可能なWindowsのいずれかのエディションが必要です。また、IISで実行することもできます(図)。

Virtual PC上のWindows 2003 ServerのIISで実行(IE6とIE7をクライントとして使用中)
Virtual PC上のWindows 2003 ServerのIISで実行(IE6とIE7をクライントとして使用中)

 クライアント側スクリプトの一部ではprototype.js(MITライセンス)を利用しています。ただし、prototype.jsについてはサンプルのアーカイブ内に含めてあります。

注意事項

 本記事のサンプルのクライアントとして、IE6およびIE7で動作を確認しています。また、Firefox 2.0では2度目のリクエスト送信時にエラーが発生して再ロードされる現象を確認しています。従ってFirefox 2.0については受信動作以外は正しく行えないという制限を持ちます。これら以外のブラウザでの動作確認は行っていません。

 上記制限の他に、XmlHttpRequestの制限から、IEを利用した場合であっても同一プロセスからの複数のウィンドウや複数のタブでの実行はサポートしていません。

ファイル構成

 ダウンロードしたファイルはzipで圧縮してあります。展開すると「CometChat」というディレクトリを頂点としたディレクトリ階層ができます。Visual Studio 2005を利用している場合は[ファイル]メニューの[開く]-[Webサイト]を、Visual Web Developer 2005 Express Editionを利用している場合は[ファイル]メニューの[Webサイトを開く]-[ファイルシステム]を利用して、「CometChat」ディレクトリを開いてください。

ルートディレクトリ

  • Web.Config
  • ASP.NET構成ファイルです。拡張子chatを後述のChatHandlerクラスに割り当てています。なお、デバッグをtrueに設定しているので、IISへこのディレクトリを直接組み込む場合は設定し直してください。
  • Default.aspx
  • チャットアプリケーションのクライアント用HTMLです。Comet用のXmlHttpRequest操作にはprototype.jsを利用しています。またメッセージの送信にはASP.NETのクライアントコールバックを利用しています。
  • Default.aspx.cs
  • Default.aspxのソースコード部分です。ここではクライアントからのメッセージ送信をクライアントコールバックとして実装しています。

App_Codeディレクトリ

  • ChatHandler.cs
  • 非同期HTTPハンドラを利用してCometを実装したメッセージ送信用クラスです。

cssディレクトリ

  • chat.css
  • Default.aspx用のスタイルシートです。

jsディレクトリ

  • prototype.js
  • Sam Stephenson氏が開発したJavaScriptライブラリです。チャットアプリケーションではComet要求の送受信に利用しています。

解説(1/2)

ASP.NETの非同期HTTPハンドラ

 Cometのキーとなる考え方は、クライアントからのXmlHttpRequestを使ったリクエストを一旦保留して、サーバー上のイベントの発生によってレスポンスを返す、という点にあります。通常、Webサーバーはこのような動作を想定していません。よくあるWebサーバーの実装は、クライアントからリクエストを受け付けるとスレッドプールからワーカスレッドを1つ確保して、そのスレッドにレスポンスを作成させるというものです(図)。この動作を前提とするWebサーバーでCometを実現しようとすると、クライアントがある程度の数になった時点でスレッドプールが枯渇してしまいます。

アイドル時にはワーカスレッドはプールされている
アイドル時にはワーカスレッドはプールされている
リクエストに対してプールからワーカスレッドを割り当てる
リクエストに対してプールからワーカスレッドを割り当てる
すべてのスレッドが処理中のため、クライアントからの要求を受けられない
すべてのスレッドが処理中のため、クライアントからの要求を受けられない

 ASP.NETには非同期HTTPハンドラと呼ばれる、時間がかかる処理の途中でスレッドを一旦解放して、スレッドプールの枯渇を防止するための実装パターンが用意されています(図)。

ASP.NETの非同期HTTPハンドラの処理シーケンス
ASP.NETの非同期HTTPハンドラの処理シーケンス

 ASP.NETは非同期HTTPハンドラを利用して次のようにクライアントからのリクエストを処理します。なお、HTTPハンドラはオブジェクトを複数のリクエストで共有するためのプロトコルを持つため、実際の処理はもう少し複雑です。

  1. クライアントからのリクエストURIのファイル名や拡張子をキーにして「Web.config」のhttpHandlers要素から処理を実行するHTTPハンドラを検索します。
  2. 該当するオブジェクトを生成します。
  3. もし、登録されていたクラスがHTTPハンドラファクトリであれば、適切なHTTPハンドラのオブジェクトを作成させてそれを利用します(3の冒頭に戻ります)。
  4. もし、同期HTTPハンドラであればProcessRequestメソッドを呼び出してレスポンスをクライアントへ返します(終了)。
    もし、非同期HTTPハンドラであれば、BeginProcessRqeuestメソッドを呼び出して処理を開始します(4.へ進みます)。この時、処理完了時に呼び出しを受けるデリゲートを引数に与えます。
  5. 非同期HTTPハンドラはバックグラウンドタスクからのイベントを受け付けるIAsyncResultインターフェイスを実装したオブジェクトをASP.NETへ返します。
  6. ASP.NETはスレッドをプールへ戻します。
  7. バックグラウンドタスクからの終了通知を受けたオブジェクトは3.で与えられたデリゲートを呼び出します。
  8. ASP.NETは非同期HTTPハンドラのEndProcessRequestメソッドを呼び出してレスポンスをクライアントへ返します(終了)。

 MSDNを読む限りでは、ASP.NETに非同期HTTPハンドラを用意した意図は、サーバーサイドで他のホストが提供するWebサービスを呼び出した場合に生じる待ち時間の有効活用のようです。しかし、この機構がCometを実装するのにも有効なことは明らかです。なぜならば、Cometの実装の要がまさに、イベントが発生するまで無駄になるリソース(ここではスレッド)の解放だからです。ASP.NETには非同期HTTPハンドラとして、あらかじめリクエスト処理を一時的に待ち状態に置くための機構が組み込まれています。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
解説(2/2)

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

arton(アートン)

専門は業界特化型のミドルウェアやフレームワークとそれを利用するアプリケーションの開発。需要に応じてメインフレームクラスから携帯端末までダウンサイジングしたりアップサイジングしたりしながらオブジェクトを連携させていくという変化に富んだ開発者人生を歩んでいる。著書に『Ruby③ オブジェクト指向とはじめての設計...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1081 2008/08/19 16:36

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング