速習!node.js + socket.io
WebSocketの動作を確認するために、以下のサイトで公開されている簡単なチャットルームを動かしてみました。
http://spechal.com/2011/03/19/super-simple-node-js-chatroom/
このサンプルは、node.js、node.jsのモジュールsocket.ioを利用します。
node.js、socket.ioの概要やインストールについては@ITの記事がまとまっています。
http://www.atmarkit.co.jp/fwcr/rensai2/nodejs01/01.html
以下、サンプルを動作させるまでの必要最低限のみの手順を説明します。
サーバーはUbuntu 10.04にセットアップしました。
node.jsのインストール
本家サイト
http://nodejs.org/
本家セットアップ手順
https://github.com/joyent/node/wiki/Installation
モジュールの取得とコンパイル(2011/04/12現在)
$ wget http://nodejs.org/dist/node-v0.4.5.tar.gz $ tar zxvf node-v0.4.5.tar.gz $ cd node-v0.4.5 $ ./configure $ make $ sudo make install
インストールの確認
$ node -v v0.4.5
※ここまで書いて後で気づきましたが、バイナリパッケージも用意されているのでapt-getでもインストール可能です。
socket.ioのインストール
本家サイト
http://socket.io/
npmのインストール
socket.ioをインストールするにはnpmというnode.jsのパッケージ管理ツールをインストールする必要があります。
インストールはcurlが必要です。インストール済みの場合は省略してください。
$ sudo apt-get install curl $ curl http://npmjs.org/install.sh | sudo sh
※/usr/local以下への書き込みが発生するので、sudoで実行します。
socket.ioのインストール
$ sudo npm install socket.io
サンプルの実行
以下をchatroom.jsで保存
var http = require('http'), // HTTP server io = require('socket.io'), // Socket.io fs = require('fs'); // File System // make a standard server server = http.createServer(function(req, res){ res.writeHead(200, {'Content-Type': 'text/html'}); // read index.html and send it to the client var output = fs.readFileSync('./index.html', 'utf8'); res.end(output); }); // run on port 8080 server.listen(8080); // listen to the server var socket = io.listen(server); // on a connection, do stuff socket.on('connection', function(client){ // broadcast the connection client.broadcast({message: client.sessionId + ' is now available'}); // when the server gets a message, during a connection, broadcast the message client.on('message', function(msg){ client.broadcast({ message: client.sessionId + ': ' + msg.message }); }); // when the server gets a disconnect, during a connection, broadcast the disconnection client.on('disconnect', function(){ client.broadcast({ message: client.sessionId + ' is no longer available' }); }); });
http://spechal.com/2011/03/19/super-simple-node-js-chatroom/より転記
上記のファイルと同じディレクトリにindex.htmlを作成します。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Chatroom</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script> <script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script> <script> // make a connection to the server var socket = new io.Socket('127.0.0.1', {port:8080, connectTimeout:3000}); // make a message buffer in case things get congested var buffer = []; socket.connect(); socket.on('connection', function(client){ // on connection, send the buffer and tell broadcast, to the server, the connection client.send({buffer: buffer}); client.broadcast({ announcement: client.sessionId + ' connected' }); }); socket.on('connect_failed', function(){ alert('The connection to the server failed.'); }); socket.on('message', function(message){ // when the client gets a message from the server, // add it to the buffer and display the message buffer.push(message); if(buffer.length > 15) buffer.shift(); appendMessage(message.message); }); socket.on('disconnect', function(client){ // on disconnect, broadcast it to the server client.broadcast({ announcement: client.sessionId + ' disconnected' }); }); // send a message to the server function sendMessage(message){ if(!message){ // get the message from the input field var msg = $("input#message").val(); $("input#message").val(''); } else { var msg = message; } if(msg.length > 0){ // stop annoying empty messages if(socket.send({message:msg})) // send the message appendMessage('You: ' + msg); // show the message } } // show the message on the screen function appendMessage(message){ $('div#chat-box').append('<div class="msg">' + message + '</div>'); } </script> </head> <body> <div id="chat-box"></div> <div id="chat-field"> <form method="post" action="" onsubmit="return false;" /> <input type="text" name="message" id="message" value="" /><input id="client" name="client" value="" type="hidden" /><input type="submit" class="button" name="send" id="send" value="Send" onclick="sendMessage();" /> </form> </div> </body> </html>
http://spechal.com/2011/03/19/super-simple-node-js-chatroom/より転記
サーバーを実行
$ node chatroom.js
http://localhost:8080にアクセス、チャットができてます。
おまけ
tcpflowで中身見てみた。
(tcpflowの使い方: http://d.hatena.ne.jp/tkman/20101203/1291343298)
$ sudo tcpflow -c port 8080 -i lo tcpflow[6325]: listening on lo 127.000.000.001.48085-127.000.000.001.08080: .~m~20~m~~j~{"message":"........."}. 127.000.000.001.08080-127.000.000.001.60915: . 127.000.000.001.08080-127.000.000.001.60915: ~m~38~m~~j~{"message":"1779476145748049: ........."} 127.000.000.001.08080-127.000.000.001.60915: . 127.000.000.001.08080-127.000.000.001.60915: . 127.000.000.001.08080-127.000.000.001.48085: ~m~5~m~~h~10 127.000.000.001.08080-127.000.000.001.48085: . 127.000.000.001.48085-127.000.000.001.08080: .~m~5~m~~h~10. 127.000.000.001.48085-127.000.000.001.08080: .~m~21~m~~j~{"message":"hello"}. 127.000.000.001.08080-127.000.000.001.60915: . 127.000.000.001.08080-127.000.000.001.60915: ~m~39~m~~j~{"message":"1779476145748049: hello"}
「.~m~20~m~~j~{"message":"........."}.」の.....は日本語のメッセージです。エンコードUTF-8で送信されています。
「あ」を送信したときのダンプ
>| .
0000000F 00 7e 6d 7e 31 38 7e 6d 7e 7e 6a 7e 7b 22 6d 65 .~m~18~m ~~j~{"me
0000001F 73 73 61 67 65 22 3a 22 e3 81 82 22 7d ff ssage":" ..."}.