ErlangでCometしてみた.
(iframe方式は結局だめそうなので,Cometに)
Comet チャットサンプル
実装はきわめて手抜きです.あくまでサンプルとして.
ソース:
chat.erl (22行.etsテーブルの初期化)
chat.yaws (72行.サーバ側の実装)
index.html (52行.HTML+JS)
※別途jqueryが必要
こんだけ短いソースでも,ちゃんとCometできるし,C10Kにも対応できる.(問題はいろいろあるコードだけど)
いろいろちゃんと実装したとしても,かなりシンプルに仕上がると思う.
Comet の正しい使い方で紹介されているプログラミングモデルのどれにも当てはまらない新しい方式,といえるかも.
Cometのために特殊な実装をする必要もないし,I/O多重化など実装がめんどくさい手法を使う必要もない.
普通に各リクエストの処理を書いて,新規メッセージを待つ部分ではそのまま待つコードをかける.
なお,yawsでそのまま実行すると,PIPELININGの相性問題が生じます.
yawsのソースの yaws.erl を
yaws.erl: ["Server: Microsoft-IIS/5.0; Yaws/", yaws_generated:version(), " Yet Another Web Server\r\n" |
というように書き換えれば解決.
最初HTTP/1.1を1.0に書き換えたのだけど,IE6でうまく表示できなくなってしまった.
1.0なのに1.1規格onlyな応答を返したりしていたせいかもしれない.
上のIISを騙る方法では無事成功.IE6/IE7/Firefox/Operaでは動作確認できた.
この辺は,Comet の正しい使い方,が大変参考になりました.
----
追記:改良した.
入退室管理,時刻表示,などをつけて,色々まずかった部分を修正.
だいぶソースは長くなったものの,Erlangが250行弱に,HTML+JSが100行くらい.
Comet チャットサンプル
ソース:
chat.erl (ログの管理など)
chat.yaws (HTTP処理)
index.html (HTML+JS)
※別途jqueryが必要
----
追記:更に改良した.
・IE7利用時にクッキーの管理がまずく,うまく入室できない事がある問題を修正
・ログをdetsで保存するようにした.再起動してもログが残るように.
・ログの保存量を100行に.1000行だと,チャット画面を開いたときに重そうだったので.
JSONで返したのをブラウザで描画するのではなくて,HTMLに変換済みのデータを最初に渡すようにすれば改善できそうだけど,めんどくさそうだったので(^^;
Comet チャットサンプル
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
index.html (HTML+JS)
※別途jqueryが必要
ソースはerl+yawsで270行くらいになった.
----
追記:
色々修正した.
・デザインをちょっとだけ.参加者一覧が上にでるとじゃまなので・・・
・発言と同時に誰かのタイムアウト処理がされたときなどに,2回連続で再接続させるのは無駄なのでタイミングを調整
・発言が続くとタイムアウトしない問題を修正
・入室直後に参加者一覧に追加されない問題を修正
・チャットの部屋をブックマークして再度参照した場合,クッキーの関係で正常に処理されないことがあったので,リダイレクトさせるのをやめた
・同じ名前で入った場合,重複しない名前をつけるように修正
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
chat_temp.html (HTML+JS)
※別途jqueryが必要
ソースが300行を超えた.
とはいえ,他の言語でやることを想像したら,かなり短いコードで書けているとは思う.
一応,簡単な負荷試験として,
chatbench.erl
とか書いて,1000人がROMっている状況でテストしてみたところ,まぁ普通に動いていたので,
そのくらいまでは耐えられそう.
Windows上で実験していたら,ポートが不足したのか,しばらくやるとクライアント側がエラーを出していたけれども(^^;
----
JSONP方式に切り替えた.
JSONP+CometはOperaでは無理と思っていたのだけど,下記を参考にさせていただいたところ,ちゃんと動くようになった.感謝.
Operaでも非同期リクエストが並列処理できる img-JSONP
IMGタグでキャッシュさせるというアイディアがすごい・・・
Comet チャットサンプル
ソース:
chat.erl (ログの管理など)
index.yaws (HTTP処理)
chat_temp.html (HTML+JS)
※別途jqueryが必要
今のサンプルは,ドメインが1つだけども,リロードするたびに適当なホスト名を生成して,ワイルドカードドメインを使えば,ドメインあたり2接続の問題は回避可能.
これでなんとか解決かな?
Safariで動作確認取れていないのが気がかりなところだけども・・・
% Mac持ってないので(^^;
追記:設置方法を別エントリに書きました.
ErlangでComet設置方法
Recent Comments