もがもがしいブログ

もがもがしく生きる

インバウンドトラフィック用にプロバイダを追加契約した

f:id:moga_shi:20131005041237p:plain

現状のネットワークこんな感じだけど以下の問題があった。

  • メインWANルータ(WZR-1750DHP)にヘアピンNAT機能がなく、iPhoneテザリング等を使わないとグローバルからの見え方が分からない。
  • WAN回線が固定IPではないため、PPPoEのセッションが切断された際にDDNSへの再登録が必要になり復旧時間が長くなる。また、VPNの接続形態に制約が生じる。
  • 検証目的でネットワーク構成を変更した際、設定ミスによりサーバへのアクセスができなくなる可能性がある。

そこで固定IP1で料金の安いグリーンネットというISPと契約した。
今はBフレでもPPPoE 2セッション貼れるので最高便利。


変更後の構成は以下の通り。

f:id:moga_shi:20131005041241p:plain

インターネットアクセス用LAN(Guest-LAN)の構成はそのままに、インバウンドの方は
ゲートウェイにFG80Cを設置して上質なエンタープライズ感を醸し出す。


試しにさくらVPSで iperf -s して、そこまでの帯域を測定した。

[root@localhost ~]# iperf -s -i 1 -t 10
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  4] local xxx.xxx.xxx.xxx port 5001 connected with xxx.xxx.xxx.xxx port xxxx  ;既存回線(Biglobe)
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0- 1.0 sec  9.54 MBytes  80.0 Mbits/sec
[  4]  1.0- 2.0 sec  10.5 MBytes  88.0 Mbits/sec
[  4]  2.0- 3.0 sec  10.6 MBytes  88.8 Mbits/sec
[  4]  3.0- 4.0 sec  10.6 MBytes  88.9 Mbits/sec
[  4]  4.0- 5.0 sec  10.7 MBytes  89.5 Mbits/sec
[  4]  5.0- 6.0 sec  10.7 MBytes  89.6 Mbits/sec
[  4]  6.0- 7.0 sec  10.7 MBytes  90.0 Mbits/sec
[  4]  7.0- 8.0 sec  10.6 MBytes  88.8 Mbits/sec
[  4]  8.0- 9.0 sec  10.7 MBytes  89.9 Mbits/sec
[  4]  9.0-10.0 sec  10.7 MBytes  89.6 Mbits/sec
[  4]  0.0-10.0 sec   106 MBytes  88.3 Mbits/sec
[  4] local yyy.yyy.yyy.yyy port 5001 connected with yyy.yyy.yyy.yyy port xxxx  ;新規回線(グリーンネット)
[  4]  0.0- 1.0 sec  8.58 MBytes  72.0 Mbits/sec
[  4]  1.0- 2.0 sec  10.4 MBytes  87.2 Mbits/sec
[  4]  2.0- 3.0 sec  10.4 MBytes  87.0 Mbits/sec
[  4]  3.0- 4.0 sec  10.3 MBytes  86.5 Mbits/sec
[  4]  4.0- 5.0 sec  10.5 MBytes  88.1 Mbits/sec
[  4]  5.0- 6.0 sec  10.4 MBytes  86.8 Mbits/sec
[  4]  6.0- 7.0 sec  10.3 MBytes  86.2 Mbits/sec
[  4]  7.0- 8.0 sec  10.4 MBytes  86.9 Mbits/sec
[  4]  8.0- 9.0 sec  10.3 MBytes  86.2 Mbits/sec
[  4]  9.0-10.0 sec  10.4 MBytes  87.1 Mbits/sec
[  4]  0.0-10.0 sec   102 MBytes  85.4 Mbits/sec

既存回線の方が若干良い値が出ているが、帯域共用ユーザーの数や
iperf -s を実行するサーバのあるISPまでの距離の影響を受けるため、あくまで参考程度。

きんモザのアリスのgif画像を取得するAPIを作った

きんモザが終わる。

毎週楽しみにしていたきんモザが。

寂しい。

アリスと会えなくなることが、寂しい。

寂しいので、アリスのgif画像を取得できるAPIを作った。

http://mogashi.com/alice/

クエリストリング無しでアクセスするとランダムで Content-Type: image/gif な画像が降ってくる。

クエリストリングに使える有効なパラメータは以下の通り。

パラメータ説明
id画像を一意に識別する ID。これを指定すると ep, no の指定は無効化される。
ep話数。ep=1 なら第1話。no と一緒に指定して使う。なお作者は第6話のたこ焼きのシーンを作成して満足したため第7話以降のgif画像は存在しない。
10/5追記:11話のアリスの泣き顔に心を打たれたためgif画像を追加した。ついでに12話まで作成した。
no話数の中の順番。no=1 に近いほど序盤のシーンになり、数が大きくなると終盤のシーンになる。たとえば ep=4&no=6 とかにすると「わたし、何もあげられるものないから、歌をうたうよ!」のシーンになる。かわいい。


そういえば ThinkPad 55Y9024 キーボードのQキーが購入後4ヶ月でぶっ壊れた。エンタープライズ、案外脆い。





続・IEEE802.11ac Draft版準拠ルータ WZR-1750DHPの通信速度をテストする

前回の記事
IEEE802.11ac Draft版準拠ルータ WZR-1750DHPの通信速度をテストしたかった - もがもがしいSEブログ
があまりにアレだったので、どうしたものかと考えあぐねていたところ、
@caplioさんからiperfというツールを勧められたので試してみました。
調べたところ、iperfはメモリ間の転送速度を計測するので、HDDがボトルネックになることはないようです。

新しい計測方法は以下の通り。

  • iperfでTCP/UDPのパケットを10秒間×5回送信し、受信側の速度を測定。


PCのスペックは前回と同じですが、一応再掲。

  • 左側…自作PCCore i5 3570, DDR3-1600 8GBx2)
  • 右側…Let's Note CF-S10(Core i5 2540M, DDR3-1066 4GB)

自作PCのアイコンがノートPCになってるのは気にしないでくださいw


構成1

f:id:moga_shi:20130401004736p:plain

まずは有線接続から。右側のPC(Let's Note)から左側のPC(自作PC)に送信します。

$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50662
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   742 MBytes   622 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50664
[  4]  0.0-10.0 sec   768 MBytes   644 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50665
[  4]  0.0-10.0 sec   791 MBytes   663 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50666
[  4]  0.0-10.0 sec   772 MBytes   647 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50667
[  4]  0.0-10.0 sec   802 MBytes   673 Mbits/sec

$ iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 52112
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec   0.001 ms    0/  893 (0%)

TCPで620~670Mbps、UDPで1Mbps。
UDPが異常に遅いですね。
帯域幅のデフォルトが1Mbpsになってるからかなと思って、送信側に -b 2000M のオプションを付けて再計測。


$ iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 49690
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams
[  3]  0.0-10.0 sec   933 MBytes   783 Mbits/sec   0.060 ms 1769/667521 (0.27%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 49691
[  4]  0.0-10.0 sec   914 MBytes   767 Mbits/sec   0.008 ms 7392/659488 (1.1%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 49692
[  3]  0.0-10.0 sec   944 MBytes   792 Mbits/sec   0.020 ms  999/674085 (0.15%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 49693
[  4]  0.0-10.0 sec   949 MBytes   796 Mbits/sec   0.060 ms  807/678055 (0.12%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 49694
[  3]  0.0-10.0 sec   943 MBytes   791 Mbits/sec   0.059 ms  870/673581 (0.13%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order

770~800Mbpsくらいになりました。
それらしい値が出たので次からは同じオプションを使って計測します。


2013/04/10追記:
【清水理史の「イニシャルB」】 NECアクセステクニカ「AtermWG1800HP」VS バッファロー「WZR-1750DHP」 - INTERNET Watch
の記事の計測方法通り、サーバ側で

iperf -s -w <TCPウィンドウサイズ>

クライアント側で

iperf -c <サーバ側IPアドレス> -w <TCPウィンドウサイズ>

を実行してTCPのウィンドウサイズを256KBや4MBに変更したところ、通信速度の計測値が改善しました。
実行結果を載せると長くなるので、記事の最後のグラフに反映します。


構成2

f:id:moga_shi:20130401005058p:plain

右側のPCから左側のPCに、11acで送信します。

$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 50616
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec  80.8 MBytes  67.6 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 50617
[  4]  0.0-10.0 sec  90.5 MBytes  75.8 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 50618
[  4]  0.0-10.0 sec  92.4 MBytes  77.4 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 50619
[  4]  0.0-10.0 sec  55.2 MBytes  46.2 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 50620
[  4]  0.0-10.2 sec  92.2 MBytes  75.7 Mbits/sec

$ iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 56657
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams
[  3]  0.0-10.0 sec   259 MBytes   217 Mbits/sec   0.140 ms  621/185156 (0.34%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 52857
[  4]  0.0-10.0 sec   262 MBytes   220 Mbits/sec   0.127 ms  331/187315 (0.18%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 52858
[  3]  0.0-10.0 sec   259 MBytes   217 Mbits/sec   0.011 ms    0/184873 (0%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 52859
[  4]  0.0-10.0 sec   261 MBytes   219 Mbits/sec   0.217 ms   47/185996 (0.025%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.10 port 52860
[  3]  0.0-10.0 sec   258 MBytes   217 Mbits/sec   0.157 ms  151/184506 (0.082%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order

TCPは65~75Mbps、UDPは220Mbpsくらい。


構成3

f:id:moga_shi:20130401010256p:plain

2台のPCをルータに有線で接続し、ルータ同士を2.4GHz + 5GHzの同時使用でつないだ構成。

$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50699
[ ID] Interval       Transfer     Bandwidth

[  4]  0.0-10.0 sec   181 MBytes   152 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50700
[  4]  0.0-10.0 sec   181 MBytes   151 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50702
[  4]  0.0-10.0 sec   184 MBytes   154 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50706
[  4]  0.0-10.0 sec   186 MBytes   156 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 50707
[  4]  0.0-10.0 sec   181 MBytes   151 Mbits/sec

$ iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 61804
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams

[  3]  0.0-10.0 sec   819 MBytes   685 Mbits/sec   0.066 ms 100875/684943 (15%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 61805
[  4]  0.0-10.3 sec   837 MBytes   685 Mbits/sec  13.589 ms 95986/693305 (14%)
[  4]  0.0-10.3 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 61806
[  3]  0.0-10.0 sec   804 MBytes   672 Mbits/sec   0.367 ms 119657/693048 (17%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 61807
[  4]  0.0-10.0 sec   804 MBytes   672 Mbits/sec   0.075 ms 117589/691152 (17%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.99 port 61808
[  3]  0.0-10.0 sec   835 MBytes   698 Mbits/sec   0.110 ms 96913/692708 (14%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order

TCPで150Mbps、UDPで670~700Mbps。


構成4

f:id:moga_shi:20130401011201p:plain

$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 51116
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec  48.5 MBytes  40.6 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 51117
[  4]  0.0-10.3 sec  30.0 MBytes  24.5 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 51118
[  4]  0.0-10.0 sec  59.4 MBytes  49.7 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 51119
[  4]  0.0-10.0 sec  43.4 MBytes  36.3 Mbits/sec
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 51120
[  4]  0.0-10.0 sec  49.5 MBytes  41.5 Mbits/sec

$ iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 64.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 58049
[ ID] Interval       Transfer     Bandwidth        Jitter   Lost/Total Datagrams

[  3]  0.0-10.0 sec   179 MBytes   150 Mbits/sec   0.130 ms    0/127534 (0%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 58050
[  4]  0.0-10.0 sec   175 MBytes   147 Mbits/sec   0.103 ms   20/125107 (0.016%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 58051
[  3]  0.0-10.0 sec   178 MBytes   149 Mbits/sec   0.100 ms    0/127115 (0%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order
[  4] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 58052
[  4]  0.0-10.0 sec   174 MBytes   146 Mbits/sec   0.178 ms   29/124125 (0.023%)
[  4]  0.0-10.0 sec  1 datagrams received out-of-order
[  3] local 192.168.11.9 port 5001 connected with 192.168.11.11 port 58053
[  3]  0.0-10.0 sec   173 MBytes   146 Mbits/sec   0.092 ms    0/123745 (0%)
[  3]  0.0-10.0 sec  1 datagrams received out-of-order

TCPで40Mbps、UDPで150Mbps。
構成2に比べて転送速度が3分の2程度に下がってしまっているのは、ルータをかませたことが原因でしょうか。
壁や天井の影響がそこまでひどくないのであれば、親機に直接つないだ方が速度が出そうです。

ちなみに、壁を1枚挟んだ状態で”左側PC←(有線)←ルータ←(無線11ac)←右側PC”の構成を試したところ、
TCPで45Mbps、UDPで160Mbpsくらいでした。


比較

最後に構成別の測定結果(中央値)をグラフにして掲載します。

f:id:moga_shi:20130410002508p:plain

全体的に、無線を経由すると速度が低下するようですね。
バッファローの測定結果では11acで最低でも500Mbpsは出ていたらしいですが・・・。
ただ、自分の測定方法がいい加減なので、メモリやバスなどの転送速度がボトルネックになっていたり、
ルータの設定方法が甘かったりして、やり方によってはもっと好成績を出せるのかもしれません。

まだひよっこSEなもので、ここをこうしたらいいよ!っていうアドバイスがあればお願いします。
興味を惹くものがあれば、ぜひ人柱としてIYH!!!させていただきますw

2013/04/10追記:
iperfにウィンドウサイズのオプションを追加したところ、計測値が劇的に改善しました。
ファイルの転送速度が、構成2でおよそ130Mbps、構成3でおよそ400Mbpsなので、感覚には割と合っています。
PCとルータ間を無線で接続した時の通信速度低下が気になりますが、今後のファームウェアアップデート等で
改善されていくのかもしれません。

IEEE802.11ac Draft版準拠ルータ WZR-1750DHPの通信速度をテストしたかった

この記事はObsoleteになりました。
続・IEEE802.11ac Draft版準拠ルータ WZR-1750DHPの通信速度をテストする - もがもがしいSEブログ
をご覧ください。

先月1日、総務省によるIEEE802.11acの認可の目処が立ち、
報道を受けた各社が相次いでIEEE802.11ac対応機器の発売を予告しました。
その中の一つ、BUFFALO製のWZR-1750が3/28に発売されまして、
IYHer的衝動を抑えきれずに2台購入したので、通信テストを行ってみました。
(正確には後述の通り、行ってみたかった、ですが……)

構成は4パターンで、速度測定に用いた方法は以下の2通りです。

  • NetMiでTCPパケットを30秒間送受信し、平均送受信速度を測定。
  • 大容量のファイルを送受信し、おおよその平均送受信速度を測定。

なお、使用したPC2台のスペックはこちら。

構成1

f:id:moga_shi:20130401004736p:plain

PC同士を有線LANでつないだだけの構成。
今まで100BASE-TXのルータを使っていたので、どれくらい早くなるかなぁと思って試してみました。

NetMiでは393Mbps、ファイルの送受信はおよそ400Mbpsでした。
普通に800Mbps以上は出ると思っていたので、あれ?という感想です。


構成2

f:id:moga_shi:20130401005058p:plain

一方のPCを有線、もう一方のPCを無線でつないだ構成。

5GHzの時はNetMiで18Mbps, ファイル送受信で140Mbps。
2.4GHzの時はNetMiで22Mbps, ファイル送受信で95Mbps。
この辺りから計測結果の信憑性がまるでダメになってきます。


構成3

f:id:moga_shi:20130401010256p:plain

一方のルータを親機、もう一方のルータを中継機として、PC-ルータ間は有線でつなぐ構成。

NetMiでは31Mbps、ファイルの送受信はおよそ520Mbpsでした。
……何なんでしょう、この差は。


構成4

f:id:moga_shi:20130401011201p:plain

構成3で、一方のPCを無線接続にしたもの。

5GHzの時はNetMiで10Mbps, ファイル送受信で100Mbps。
2.4GHzの時はNetMiで18Mbps, ファイル送受信で80Mbps。


まとめ

誰か正しい測定方法を教えてください。

ジャンボフレームとかLANケーブルとかディスクの読み出し速度とか、
色々ボトルネックになりそうなところはありますが、何が原因かはまだ分かっていません。

今日から社会人2年目。そろそろ自分のコアスキルに自信を持ちたいところです。

有線LANと無線LANの優先度を切り替える

会社でノートPCを使っていると、無線LANと有線LANを使い分けたいことがあります。
イントラネットには無線でしかアクセスできないけど、
運用LANには有線でしかアクセスできないみたいなパターンですね。
こんな時、PCのルーティングテーブルが適切に設定されていないと、
無線で通信するべきネットワークに有線でつないだり、その逆の事態が生じたりします。
これを解消するのがrouteコマンドです。
クライアントOSはWindows 7、ネットワーク構成は以下の前提で説明していきます。

f:id:moga_shi:20130330235647p:plain

まず、route printコマンドでPCの現在のルーティングテーブルを確認します。

C:\Users\u123456>route print
===========================================================================
インターフェイス一覧
 11...f0 de f1 ** ** ** ......Intel(R) 82579LM Gigabit Network Connection
 12...10 0b a9 ** ** ** ......Intel(R) Centrino(R) Advanced-N 6205
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイス  メトリック
          0.0.0.0          0.0.0.0        10.192.1.254      10.192.1.100     20
       10.192.1.0    255.255.255.0            リンク上      10.192.1.100    266
     10.192.1.100  255.255.255.255            リンク上      10.192.1.100    266
     10.192.1.255  255.255.255.255            リンク上      10.192.1.100    266
        127.0.0.0        255.0.0.0            リンク上         127.0.0.1    306
        127.0.0.1  255.255.255.255            リンク上         127.0.0.1    306
  127.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上      10.192.1.100    266
  255.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
  255.255.255.255  255.255.255.255            リンク上      10.192.1.100    266
===========================================================================
固定ルート:
  なし


この構成だと、有線LANでしか接続できないネットワークや
社内のプロキシでブラックリストに登録されているサイトにアクセスできません。
ここに有線LANを接続します。

f:id:moga_shi:20130331005228p:plain

C:\Users\u123456>route print
===========================================================================
インターフェイス一覧
 11...f0 de f1 ** ** ** ......Intel(R) 82579LM Gigabit Network Connection
 12...10 0b a9 ** ** ** ......Intel(R) Centrino(R) Advanced-N 6205
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイス  メトリック
          0.0.0.0          0.0.0.0        10.192.1.254      10.192.1.100     20
       10.192.1.0    255.255.255.0            リンク上      10.192.1.100    266
     10.192.1.100  255.255.255.255            リンク上      10.192.1.100    266
     10.192.1.255  255.255.255.255            リンク上      10.192.1.100    266
        127.0.0.0        255.0.0.0            リンク上         127.0.0.1    306
        127.0.0.1  255.255.255.255            リンク上         127.0.0.1    306
  127.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
      192.168.1.0    255.255.255.0            リンク上     192.168.1.100    261
    192.168.1.100  255.255.255.255            リンク上     192.168.1.100    261
    192.168.1.255  255.255.255.255            リンク上     192.168.1.100    261
        224.0.0.0        240.0.0.0            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上     192.168.1.100    261
        224.0.0.0        240.0.0.0            リンク上      10.192.1.100    266
  255.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
  255.255.255.255  255.255.255.255            リンク上     192.168.1.100    261
  255.255.255.255  255.255.255.255            リンク上      10.192.1.100    266
===========================================================================
固定ルート:
  なし


有線LANに接続しているので有線LAN向けの通信ができそうですが、デフォゲが無線LANルータの方を向いているので、
宛先ノードが自分と同じネットワークに存在しない場合、
パケットが無線LANルータの方に行ってしまいます。
かといって、すべてのパケットを有線LAN経由にすると、今度は無線LANでしか
通信できないネットワークと通信できなくなってしまいます。


案1

要件を以下のように定めます。

f:id:moga_shi:20130331005230p:plain

  • 無線LAN経由でしか通信できないネットワーク宛のパケットは必ず無線LANルータ経由にする。
  • 宛先が自分と同じネットワークに存在しないパケットは、
    • PCにLANケーブルが接続されている時はそっち経由にする。
    • 接続されていない時は無線LANルータ経由にする。


実行するコマンドは以下の通りです。

C:\Users\u123456>route -p add 0.0.0.0 mask 0.0.0.0 192.168.1.254 metric 10

デフォルトルートを有線LANルータ宛に設定。メトリックが無線LANルータよりも小さくなるように。
-pは再起動後もルートを維持するオプション。


C:\Users\u123456>route -p add 10.240.0.0 mask 255.255.0.0 10.192.1.254

イントラネット宛の通信は必ず無線LANルータ経由にする。
メトリックは省略すると1になる。


なお、不幸にも有線LANと無線LANでネットワークアドレスが重複してしまう場合は、
route printコマンドの一番上に出てくるインタフェースを番号で指定します。(今回は不要です)

C:\Users\u123456>route -p add 10.240.0.0 mask 255.255.0.0 10.192.1.254 if 12


これで完成となりますが、実はこの設定だと以下の問題があって実用性に乏しいです。

  • DNSの名前解決が有線LAN経由になるため、社内システムのホスト名を解決できない。

案2

上記の問題を解決するために、仕様を以下のように変更します。

f:id:moga_shi:20130331005231p:plain

  • 基本は無線LANルータ経由で通信する。
  • 有線LANで接続したいネットワークだけroute addで追加する。

コマンドは次のとおりです。

C:\Users\u123456>route delete 0.0.0.0
C:\Users\u123456>route delete 10.240.0.0

先程登録したルートを削除します。


C:\Users\u123456>route -p add 0.0.0.0 mask 0.0.0.0 10.192.1.254 metric 20

デフォルトゲートウェイ無線LANルータにします。


C:\Users\u123456>route -p add 173.194.38.96 mask 255.255.255.240 192.168.1.254

有線LANで接続したいルートを個別に登録します。
ブラウザで閲覧する時はプロキシの例外設定を忘れないようにしてください。


ルーティングテーブルの最終形は次のようになります。

C:\Users\u123456>route print
===========================================================================
インターフェイス一覧
 11...f0 de f1 ** ** ** ......Intel(R) 82579LM Gigabit Network Connection
 12...10 0b a9 ** ** ** ......Intel(R) Centrino(R) Advanced-N 6205
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイス  メトリック
          0.0.0.0          0.0.0.0        10.192.1.254      10.192.1.100     20
       10.192.1.0    255.255.255.0            リンク上      10.192.1.100    266
     10.192.1.100  255.255.255.255            リンク上      10.192.1.100    266
     10.192.1.255  255.255.255.255            リンク上      10.192.1.100    266
        127.0.0.0        255.0.0.0            リンク上         127.0.0.1    306
        127.0.0.1  255.255.255.255            リンク上         127.0.0.1    306
  127.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
    173.194.38.96  255.255.255.240       192.168.1.254     192.168.1.100      6
      192.168.1.0    255.255.255.0            リンク上     192.168.1.100    261
    192.168.1.100  255.255.255.255            リンク上     192.168.1.100    261
    192.168.1.255  255.255.255.255            リンク上     192.168.1.100    261
        224.0.0.0        240.0.0.0            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上     192.168.1.100    261
        224.0.0.0        240.0.0.0            リンク上      10.192.1.100    266
  255.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
  255.255.255.255  255.255.255.255            リンク上     192.168.1.100    261
  255.255.255.255  255.255.255.255            リンク上      10.192.1.100    266
===========================================================================
固定ルート:
  ネットワーク アドレス          ネットマスク  ゲートウェイ アドレス  メトリック

          0.0.0.0          0.0.0.0   10.168.195.254      20
    173.194.38.96  255.255.255.240    192.168.1.254       1
===========================================================================

その他

今回はWindowsのrouteコマンドをご紹介しましたが、Linuxにもrouteコマンドがあります。
書き方は異なりますが、基本的な動作は同じだと思われるので、詳しいことは以下のサイトなどをご覧ください。
Linuxコマンド集 - 【 route 】 ルーティング・テーブルを表示・設定する:ITpro


課題

案1で、名前解決だけを無線LAN経由にできれば問題は解決できたのではないかと思いますが、その方法が分かりませんでした。
分かり次第追記しますが、ご存知の方がいればご教示ください。

Node.js+Socket.IO+Express+MongoDB で実装するチャットサンプル [deprecated]

(※注:2012年当時の記事のため内容はかなり古いです。いつか書き直したい・・・)

2012年もスタートして早5日。
せっかくの心機一転のチャンスだし、何か新しい技術を覚えてみたいと思い、WebSocket の勉強をしてみることにしました。
既にご存知の方も多いと思いますが、WebSocket とはブラウザ上で Web サーバとの双方向通信を可能にする規格のことで、
HTML5 とともに、Web アプリケーションがこれから全盛期を迎えるだろう時代にあっては必須とも言えるものです。

blog.livedoor.jp

ブラウザ上で双方向通信を行うための規格としては、これまでにも Ajax や Comet といったものがありましたが、
サーバからのプッシュ通信ができないことや負荷が高いといった問題があり、
それらを簡潔な実装で解消できる技術が求められていたようです。

Ajax, Comet, WebSocket の具体的な相違点については、こちらのスライドで詳しく説明されています。

www.slideshare.net

以上のように、WebSocket はとても将来性のある技術ですが、現時点では APIプロトコルの仕様が固まっていないことや、一部の古いブラウザが対応していないということもあり、実際にアプリケーションを作る際にはその点を考慮しなければなりません。
今回は、そうしたブラウザ間の差異を吸収し、一度の実装で全ブラウザ対応を可能にしてくれる「Socket.IO」というライブラリを使用することにしました。
また、アプリケーションを動かすサーバとして、「Node.js」という、JavaScriptで動かせるサーバを使うことにしました。
作るものはリアルタイムチャットです。

ここから実装の話に入っていきますが、便宜上、OS は CentOS を使うことにします。
それから、自分自身がroot権限で作業を行ったということもあり、あまり良くはないと思いますが、念のためroot権限で行っていきます。
まず、Node.js のインストール。

# cd /usr/local/src
# wget <a href="http://nodejs.org/dist/v0.6.5/node-v0.6.5.tar.gz" style="color:#ccf;">http://nodejs.org/dist/v0.6.5/node-v0.6.5.tar.gz</a>
# tar xzvf node-v0.6.5.tar.gz
# cd node-v0.6.5
# ./configure
# make
# make install

これで /usr/local/bin/node が作成されます。
次に、Socket.IO のインストール。

# npm install socket.io
socket.io@0.8.7 ./node_modules/socket.io

npmというのは Node Package Manager、つまり Node.js 関係のパッケージ管理システムで、これを使って Socket.IO をインストールしています。
今回は Socket.IO の v0.8.7 を使いますが、Socket.IO は 0.7系から仕様が大きく変わっており、同じコードでもバージョンによって動かなくなることがあります。
(自分はこれにハマってドキュメントの大切さを思い知りました…)

この記事の内容も数ヶ月後にはもう動かなくなっているかもしれないので、ぜひ本家のドキュメントもご覧ください。
https://github.com/LearnBoost/socket.io

続いて、Express と EJS をインストールします。
Express は Node.js アプリを作るのに必要なファイルを自動生成してくれるフレームワークで、EJS は Node.js アプリの表示機能の実装をちょっと楽にしてくれるテンプレートエンジンです。

# npm install -g express ejs
# express sandbox
# cd sandbox

# sandbox 内で必要なモジュールが使えるようにします。
# 元のモジュールをグローバルオプションでインストールしているので npm link express ejs でいけるはずなのですが
# なぜがうまくいかなかったので、リソースの無駄遣いと知りつつ二回インストールしています。

# npm install express ejs

express sandbox を実行すると、sandbox というディレクトリが作成されて、その中に Node.js アプリに必要なファイル郡が作られます。
具体的には以下の通り。

sandbox
│
├ node_modules
│  │
│  ├ express
│  │  └...
│  └ jade
│     └...  // 今回は使わない
├ views
│  ├ layout.jade  // 今回は使わない
│  └ index.jade  // 今回は使わない
│
├ routes
│  └ index.js  // 今回は使わない
│
├ public
│  ├ stylesheets
│  │  └ style.css
│  ├ javascripts
│  └ images  // 今回は使わない
│
├ package.json
│
└ app.js  // サーバーサイドで動くJavaScriptファイル

この状態で

# node app.js

を実行して、http://203.0.113.0:3000(サーバのIPアドレスを203.0.113.0と仮定しています)
にアクセスすると、「Welcome to Express」という画面が表示されるかと思います。

以下ではこの app.js やテンプレートファイルを書き換えてチャットアプリを作っていきます。

まず、必要なロジックとして挙げられるのは

  • クライアント端末からサーバにメッセージを送信する機能(クライアント側で実装)
  • サーバが受信したメッセージを全てのクライアント端末に対して送信する機能(サーバ側で実装)
  • クライアント端末が受信したメッセージを画面に表示する機能(クライアント側で実装)

の3つです。
(以下、クライアントからサーバに送信するメッセージの名前を 'msg send', サーバからクライアントに送信するメッセージの名前を 'msg push' とします。)

これに表示用のテンプレートファイルを加えた結果、ファイル構成は

sandbox
│
├ node_modules  // 各種モジュール
│  │
│  ├ express
│  │  └...
│  └ ejs
│    └...
├ views
│  └ index.ejs  // 表示用テンプレート
│
├ public    // クライアント側で使用するファイル群
│  │
│  ├ stylesheets
│  │  └ style.css
│  └ javascripts
│     └ client.js  // クライアント側のJavaScriptファイル
│
├ package.json
│
└ app.js  // サーバーサイドで動くJavaScriptファイル

となります。まずはクライアントの表示用ファイルから。

[index.ejs]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" href="/stylesheets/style.css" />
  </head>
  <body>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1.4.4");</script>
    <script type="text/javascript" src="/socket.io/socket.io.js"></script>
    <script type="text/javascript">
      var port = <%= port %>;
    </script>
    <script type="text/javascript" src="/javascripts/client.js"></script>
    <h1><%= title %></h1>
    <form id="form1">
      <input type="text" id="message" />
      <input type="submit" value="送信" />
    </form>
    <ul></ul>
  </body>
</html>


必要なファイルの読み込みと、簡単なタグだけです。<%= port %> と <%= title %> のところには、後で [app.js] で定義する値が入ります。

続いてクライアントのJavaScript


[client.js]

$(function() {
  var socket = new io.connect('http://203.0.113.0:'+port);

  // ▼ チャットフォーム ▼
  $('#form1').submit(function() {
    msg = $('#message').val();
    msg = sanitize(msg);
    socket.emit('msg send', msg);
    $('#message').val('');
      return false;
    });
    // ▲ チャットフォーム ▲
    
    // メッセージ受信
    socket.on('msg push', function(msg, date) {
      $('ul').prepend('<li>'+msg+' ('+date+')</li>');
    });
});

function sanitize(str) {
  str = str.replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
  return str;
}

サーバ(203.0.113.0:3000)に接続した後、フォームのsubmitボタンを押すと
サーバに対して 'msg send' という名前のメッセージを、変数 msg とともに送信します。
メッセージはサーバ側で処理された後、'msg push' という名前のメッセージを、
変数 msg, date とともに返すものとしています。

最後にサーバ側のJavaScript


[app.js]

var express = require('express')
  , ejs = require('ejs')
  , io  = require('socket.io')

var app = module.exports = express.createServer();

var title = 'チャットテスト';
var port = 3000;

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.set('view options', { layout: false });
  app.use(express.static(__dirname + '/public'));
});
app.get('/views', function(req, res) {
  res.render('index', { locals: { port:port, title:title } });
});

app.listen(port);
console.log("Express server listening on port %d", app.address().port);

var socket = io.listen(app);

// ▼ 接続時実行 ▼
socket.sockets.on('connection', function(client) {

  // ▼ クライアントからサーバへメッセージ送信 ▼
  client.on('msg send', function(msg) {
    date = getDateAndTime();
    if (msg == '') return;
    client.emit('msg push', msg, date);
    client.broadcast.emit('msg push', msg, date);
  });
  // ▲ クライアントからサーバへメッセージ送信 ▲
});
// ▲ 接続時実行 ▲

// 現在の日時を YYYY/MM/DD hh:mm:dd 形式で返す関数
function getDateAndTime() {
  dd = new Date();
  year = (dd.getYear() < 2000 ? dd.getYear()+1900 : dd.getYear() );
  month = (dd.getMonth() < 9 ? "0" + (dd.getMonth()+1) : dd.getMonth()+1 );
  day = (dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate() );
  hour = (dd.getHours() < 10 ? "0" + dd.getHours() : dd.getHours() );
  minute = (dd.getMinutes() < 10 ? "0" + dd.getMinutes() : dd.getMinutes() );
  second = (dd.getSeconds() < 10 ? "0" + dd.getSeconds() : dd.getSeconds() );
  return year + "/" + month + "/" + day + " " + hour + ":" + minute + ":" + second;
}

ここで、

# node app.js

を実行してから http://203.0.113.0:3000/views にアクセスすると、socket.sockets.on の中身が実行され、'msg send' というメッセージの受信待ち状態になります。(client.on の部分)
メッセージを受信すると、

client.emit('msg push', msg, date);

でそのメッセージの送信者に対して 'msg push' という名前のメッセージを返信するほか、

client.broadcast.emit('msg push', msg, date);

で接続中の残り全てのクライアントに対して同じメッセージを送信します。

ブラウザでメッセージを送信すると、他のブラウザにも瞬時に反映されることが確認できます。

以上で最低限の機能の実装は終わりです。
この状態だと、入力したメッセージはその時チャットを開いていたブラウザに表示されるだけでそのまま消えてしまうので、会話が成立するためにはお互いが同じタイミングで居合わせる必要があります。
このままでは実用性に乏しいため、MongoDB というデータベースを使ってログの保存・読み込み機能を実装します。
MongoDB の概要、Node.js との相性の良さについてはこちらのスライドが詳しいです。

www.slideshare.net

インストール作業、やはりroot権限でやっています。
まずは yumリポジトリを追加。こちらのブログを参考にしました。

http://memo.yomukaku.net/entries/tiSGwUw

# vi /etc/yum.repos.d/10gen.repo
[10gen] 
name=10gen Repository 
baseurl=<a href="http://downloads-distro.mongodb.org/repo/redhat/os/x86_64" style="color:#ccf;">http://downloads-distro.mongodb.org/repo/redhat/os/x86_64</a>
gpgcheck=0
enabled=0

# yum search mongo --enablerepo=10gen
=========================== Matched: mongo ===========================
libuninum.x86_64 : Library for converting unicode strings to numbers
mongo-10gen.x86_64 : mongo client shell and tools
mongo-10gen-server.x86_64 : mongo server, sharding server, and support
                          : scripts
mongo18-10gen.x86_64 : mongo client shell and tools
mongo18-10gen-server.x86_64 : mongo server, sharding server, and
                            : support scripts

# yum install mongo-10gen-server.x86_64 --enablerepo=10gen
# mongod --version
db version v2.0.2, pdfile version 4.5
# npm install mongodb		// sandbox ディレクトリ直下で実行

/usr/bin に MongoDB とその関連モジュールがインストールされました。
起動スクリプトは /etc/rc.d/init.d/mongod に、設定ファイルは /etc/mongod.conf にあります。

せっかくなので MongoDB がどんなものなのか使ってみましょう。

# mongo
MongoDB shell version: 2.0.2
connecting to: test
> show dbs
admin   (empty)
local   (empty)
> db.things.insert({"name": "rice ball", "price": 105})
> db.things.insert({"name": "cup noodle", "price": 188})
> db.things.insert({"name": "water", "price": 98})
> db.things.find()
{ "_id" : ObjectId("4f044fb116df0fb8470aae4d"), "name" : "rice ball", "price" : 105 }
{ "_id" : ObjectId("4f04504916df0fb8470aae4e"), "name" : "cup noodle", "price" : 188 }
{ "_id" : ObjectId("4f04505e16df0fb8470aae4f"), "name" : "water", "price" : 98 }</div>

test というデータベース配下の things というコレクションに 3件のドキュメントを追加しています。
コレクションはリレーショナルデータベースではテーブルに相当するもので、ドキュメントは行に相当するものです。
データ構造を決めずにいきなりデータを追加できるという手軽さが面白いです。

ドキュメントを探す時は

> db.things.find({"name": "rice ball"})
{ "_id" : ObjectId("4f044fb116df0fb8470aae4d"), "name" : "rice ball", "price" : 105 }

のようにできます。

> db.things.update({name: "rice ball"}, {$set: {price: 210}})
> db.things.find({"name": "rice ball"})
{ "_id" : ObjectId("4f044fb116df0fb8470aae4d"), "name" : "rice ball", "price" : 210 }

値上がりさせてみました。

それでは実際に MongoDB を使って、先程作った [client.js], [app.js] を書き換えていきます。( index.ejs はそのままです)

[client.js]

$(function() {
  var socket = new io.connect('http://203.0.113.0:'+port);

  // ▼ チャットフォーム ▼
  $('#form1').submit(function() {
    msg = $('#message').val();
    msg = sanitize(msg);
    socket.emit('msg send', msg);
    $('#message').val('');
    return false;
  });
  // ▲ チャットフォーム ▲
  
  // メッセージ受信
  socket.on('msg push', function(msg, date) {
    $('ul').prepend('<li>'+msg+' ('+date+')</li>');
  });
  
  // ログの読み込み
  socket.on('msg load', function(msg, date) {
    $('ul').append('<li>'+msg+' ('+date+')</li>');
  });
});

function sanitize(str) {
  str = str.replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
  return str;
}

チャットにアクセスした時に、サーバから 'msg load' という名前のメッセージを
クライアントが受け取り、表示する機能を加えています。


[app.js]

var express = require('express')
  , ejs = require('ejs')
  , io  = require('socket.io')
  , mongo = require('mongodb')
  , db = new mongo.Db('test', new mongo.Server('203.0.113.0', 27017, {}), {});

var app = module.exports = express.createServer();

var title = 'チャットテスト';
var port = 3000;

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.set('view options', { layout: false });
  app.use(express.static(__dirname + '/public'));
});

app.get('/views', function(req, res) {
  res.render('index', { locals: { port:port, title:title } });
});

app.listen(port);
console.log("Express server listening on port %d", app.address().port);

var socket = io.listen(app);

// ▼ 接続時実行 ▼
socket.sockets.on('connection', function(client) {
  
  // ▼ 初回アクセス時 最新20件のログを取得して送信 ▼
  db.open(function(){
    db.createCollection("comments", function(err, collection) {
      cursor = collection.find({}, {"limit":20, "sort":[['unixtime','desc']] });
      cursor.each(function(err, doc) {
        if (doc != null)
          client.emit('msg load', doc.message, doc.date);
      });
    });
  });
  // ▲ 初回アクセス時 最新20件のログを取得して送信 ▲
  
  // ▼ クライアントからサーバへメッセージ送信 ▼
  client.on('msg send', function(msg) {
    date = getDateAndTime();
    unixtime = new Date()/1000;
    if (msg == '') return;
    // comments コレクションに保存
    db.open(function() {
      db.collection("comments", function(err, collection) {
        collection.insert({"message":msg, "date":date, "unixtime":unixtime});
        console.log('*** DB insert ***');
      });
    });
    client.emit('msg push', msg, date);
    client.broadcast.emit('msg push', msg, date);
  });
  // ▲ クライアントからサーバへメッセージ送信 ▲
});
// ▲ 接続時実行 ▲

// 現在の日時を YYYY/MM/DD hh:mm:dd 形式で返す関数
function getDateAndTime() {
  dd = new Date();
  year = (dd.getYear() < 2000 ? dd.getYear()+1900 : dd.getYear() );
  month = (dd.getMonth() < 9 ? "0" + (dd.getMonth()+1) : dd.getMonth()+1 );
  day = (dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate() );
  hour = (dd.getHours() < 10 ? "0" + dd.getHours() : dd.getHours() );
  minute = (dd.getMinutes() < 10 ? "0" + dd.getMinutes() : dd.getMinutes() );
  second = (dd.getSeconds() < 10 ? "0" + dd.getSeconds() : dd.getSeconds() );
  return year + "/" + month + "/" + day + " " + hour + ":" + minute + ":" + second;
}

これでログの保存・読み込み機能ができました。

初めての記事にしてはだいぶ長くなってしまいましたが、ひとまずこれで終了します。

今回は Node.js から MongoDB にアクセスするドライバとして、

# npm install mongodb

でインストールされる node-mongodb-native を使用しましたが、この後色々チャットを改造していてコールバック地獄を味わったというのもあり、mongoose にも興味を持ちました。
また時間のあるときに試したいと思います。