2010年10月19日火曜日

リアルタイム Web とは何でゲソ?

このエントリーをはてなブックマークに追加
C# で WebSocket を試してみなイカ?


なるほどでゲソ。

ということで、WebSocket server on node.js の環境を作って、C# からの接続を試みた。

なお、今回の試行は Linux Mint 9 + Mono 2.6.7 上で行った。使用した Web ブラウザは Chromium Daily Builds 版(8.0.558.0)。


WebSocket server on node.js

Install node.js
上記リンクから、node-v0.2.3.tar.gz をダウンロードし、インストールを行う。

$ tar -xvf node-v0.2.3.tar.gz
$ cd node-v0.2.3
$ ./configure
$ make
$ sudo paco -D make install
$ node -v
v0.2.3

./configure を実行した時に、特にエラーは出なかったが、環境に応じてインストールが必要になるパッケージはあるだろう。

インストール先は「/usr/local」配下になる。

また、make test を実行する場合、実行前に「解凍先/test」配下に tmp ディレクトリを作成する必要があったり、実行してみると次のようなエラーが出力されるが

$ make test
Waf: Entering directory `/home/sta/Downloads/node-v0.2.3/build'
DEST_OS: linux
DEST_CPU: x86
Parallel Jobs: 1
Waf: Leaving directory `/home/sta/Downloads/node-v0.2.3/build'
'build' finished successfully (0.370s)
python tools/test.py --mode=release simple message
=== release test-http-upgrade-client2 ===
Path: simple/test-http-upgrade-client2
node.js:63
    throw e;
    ^
Error: ECONNREFUSED, Connection refused
    at IOWatcher.callback (net:854:22)
    at node.js:768:9
Command: build/default/node /home/sta/Downloads/node-v0.2.3/test/simple/test-http-upgrade-client2.js
[00:56|% 100|+ 130|-   1]: Done                                       
make: *** [test] エラー 1

今回の試行に支障はないので、このまま進む。

WebSocket server
上記リンクから miksago-node-websocket-server-v1.3.50-0-g976aaeb.tar.gz をダウンロードし、解凍する。

「解凍先/examples」配下にいくつかのサンプルがあるが、そのうちの chat-server.js を実行してみる。

$ tar -xvf miksago-node-websocket-server-v1.3.50-0-g976aaeb.tar.gz
$ cd miksago-node-websocket-server-fe1ac5f/examples
$ node chat-server.js
15 Oct 00:36:24 - Listening for connections.

WebSocket server の資源は「解凍先/lib」配下に存在する。今回はこれをそのまま使うが、どうやら node.js 用のパッケージマネージャーが存在するらしいので、そのパッケージマネージャーを使用したインストールを別の機会に試してみようと思う。

chat-server.js は http サーバーを含んでいるので、http://localhost:8000 でアクセスしてみると


今回の試行では、この chat-server.js とのアクセスを試してみる。

websocket-sharp

のようなものがあるだろうと考え、Google 先生に聞いてみたが、丁度いい感じのものがなかったので実装してみた。
ただし、Opening handshake 内の Sec-WebSocket-Key1、Sec-WebSocket-Key2 によるチャレンジ・レスポンスに関わる部分は未実装だ。 実装してみた。

原型および参考にしたのは、イカのリンク先。

WebSocket の仕様に関しては、イカのリンク先を参照した。

MonoDevelop からソリューションファイル websocket-sharp.sln を開いて、wsclient プロジェクトを実行することで、chat-server.js とのアクセスを試すことができる。



C# 側から送信 => Web ブラウザ側で受信、Web ブラウザ側から送信 => C# 側で受信、共に問題ないようだ。

WebSocket から受信したメッセージの表示に NotifyOSD(NotifySharp)を使用してみた。

ビルドオプションの指定で、NotifyOSD 使用の有無を切り換えられるようにした。Debug_Ubuntu および Release_Ubuntu コンフィギュレーションを選択した場合、そのオプションは有効になる。

追記: WebSocket.cs から NotifyOSD 関連のコードを削除した。wsclient.cs では NotifyOSD 使用有無のオプションは残した。

NotifyOSD 用アセンブリ notify-sharp.dll を MonoDevelop で使用するには、イカのパッケージのインストールが必要。

$ sudo apt-get install libnotify-cil-dev

NotifySharp についてはイカを参照。

メッセージを表示させるのに NotifyOSD は最適と考えて使用したわけだが、その扱いはなかなか難しいところがある。

結局分かったのは、Notification インスタンスを生成したのと同一スレッド上じゃないと、そのインスタンスをうまく扱うことはできないということ。

さらに、複数のスレッドで、Notification インスタンスを生成した場合、その動作は不安定、というか操作不能になってしまう。

1アプリ1スレッド上でしか使用不可という感じだが、何か設定があるのだろうか。

また、受け取ったメッセージをできるだけ同一の NotifyOSD メッセージウィンドウ内の末尾に追加して表示させるようにしたかったけど、該当する設定が有効にならず、同一ウィンドウ内でメッセージが書き換わるようにしかならない。他に何か設定があるのだろうか。 これは、解決した。

wsclient/wsclient.cs から抜粋。
#if NOTIFY
          Notification nf = new Notification("[WebSocket] Message",
                                             s,
                                             "notification-message-im");
          nf.AddHint("append", "allowed");
          nf.Show();
#else
ひとつのインスタンスを使い回すのではなく、その都度生成した場合、想定した表示をしてくれるようになった。

ということで、この NotifyOSD の使用については、WebSocket 本筋とはまるで関係ないが、多少知見を深めることができた。

所感

node.js + WebSocket は何だかいろいろ楽になりそうでスゲー。でも、node.js を nude.js と読み違えていたのはオレだけじゃないよね?

1 件のコメント:

sta.blockhead さんのコメント...

NotifyOSD の使用に関して追記および修正を行いました。

コメントを投稿