node.jsとsocket.ioでリアルタイムチャットシステムを作る 〜実装編〜
さて、前回でインストールが完了しましたので、
実際にプログラムをしていきます。
まず、前回、chatroomという名前のプロジェクトのひな形を作成したので、
それを起動してみましょう。
$ cd chatroom $ node app.js Express server listening on port 3000 in development mode
これで起動されましたので、
http://localhost:3000/
にアクセスすると、以下のような画面が表示されると思います。
chatroom/app.js を以下のように編集します。
var express = require('express'); var sio = require('socket.io'); var app = module.exports = express.createServer(); app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(require('stylus').middleware({ src: __dirname + '/public' })); app.use(app.router); app.use(express.static(__dirname + '/public')); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); app.listen(3000); console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); // ルーティングの設定 var routes = require('./routes'); app.get('/', routes.index);
次に chatroom/views/layout.jade を以下のように編集します。
!!! html head title= title link(rel='stylesheet', href='/stylesheets/bootstrap/bootstrap.css') link(rel='stylesheet', href='/stylesheets/style.css') script(src='/socket.io/socket.io.js') script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js') body!= body
次に、chatroom/views/index.jade を以下のように編集します。
div.container div.hero-unit a.titleLink(href="/") h1= title p test version form(action="/enter", method="post") div.input.center(style="margin-left:0px") span.label.success なまえ input.xlarge.username(name='username' , type="text ") div.center input.btn.large.primary.enterBtn(type="submit", value="はいる")
次に、chatroom/public/stylesheets/style.styl を作り以下のように編集します。
なおこれはただのスタイルなので、なくてもいいです。
div.hero-unit height 50px p.name color #00B7FD width 100% div.hero-unit p color Sienna a.titleLink:hover text-decoration none div.center text-align center input.enterBtn margin-top 40px div.chatArea text-align center margin-top 30px input.chatText input.chatBtn margin-left 10px input.username margin-left 20px table.chatTable margin auto width 60% border-bottom 1px solid #ddd td.nameTd width 25% td.chatTd width 75% p.chat text-align left div.loginUsers margin auto auto 30px width 80% div.loginUsers span margin-left 15px background-color Khaki border-radius 5px 5px 5px 5px padding 4px 7px div.chatDiv max-height 400px overflow auto
さて、ここまでかけたら、
$ node-dev app.js
で起動してみましょう。きっと初期表示画面がでるはずです。きっと。
■2,チャットルームにログインする処理
まず、chatroom/app.js に以下を追記します。
var routes2 = require('./routes/enter'); app.post('/enter',routes2.enter);
次に、chatroom/routes/enter.js を作り以下のように編集します。
exports.enter = function(req, res) { var result = {title: 'ChatRoom', username: req.body.username}; res.render('room', result); };
次に、チャットルームの画面を定義します。
chatroom/ views/room.jade を作り以下のように編集します。
div.container div.hero-unit a.titleLink(href="/") h1= title p test version div.loginUsers.alert-message.block-message.warning p strong ログインユーザ : span #{username} div.chatDiv table.chatTable tr th なまえ th tr div.chatArea form input.xlarge.chatText(name="chat", type="text") input.btn.primary.chatBtn(type="submit", value="はつげん") script(type='text/javascript') var user = '#{username}'; var sockt; $(function(){ socket = io.connect(); socket.emit('login', user); //ログインしたということをサーバーに送る socket.on('res',function(from, msg) { console.log('res# from=' + from + ', msg=' + msg); displayChat(from, msg); }); socket.on('updateLoginUsers', function(users){ console.log('updateLoginUsers# users=' + users); updateLoginUsers(users) }); $('form').submit(function(e){ chat(); return false; }); }); //ログインしているユーザの更新 function updateLoginUsers (users) { console.log(users); $('div.loginUsers p span').remove(); for (var i in users) { $('div.loginUsers p').append($('<span>').text(users[i])); } } //発言する function chat() { var msg = $('input.chatText').val(); $('input.chatText').val('').focus(); socket.emit('chat', user, msg); //発言内容をサーバーに送る $('div.chatDiv').animate({ scrollTop: 2000000 }, 'fast'); return false; } //発言内容を表示する function displayChat(from, msg) { console.log('chat: from=' + from + ', msg=' + msg); var nameDom = $('<p>').addClass('name').text(from + ' : '); var trDom = $('<tr>'); trDom.append($('<td>').addClass('nameTd').append(nameDom)); var chatDom = $('<p>').addClass('chat').text(msg); trDom.append($('<td>').addClass('chatTd').append(chatDom)); $('table.chatTable').append(trDom); }
ここまで、書けたら http://localhost:3000/ にアクセスして、「はいる」ボタンを押すと、以下の画面が出ると思います。
■3,チャット処理を書く
まず、chatroom/app.js に以下を追記します。
var io = sio.listen(app); var routes3 = require('./routes/chat'); routes3.io = io; // クライアントが接続してきたときの処理 io.sockets.on('connection', routes3.chat);
次に、chatroom/routes/chat.js を作り以下のように編集します。
exports.users = {}; exports.messages = []; exports.chat = function(client) { var users = exports.users; var messages = exports.messages; var io = exports.io; console.log(client.sessionId + 'が接続しました。'); //ログインしてきた場合の処理 client.on('login', function(user){ console.log(users); users[user] = user; client.user = user; io.sockets.emit('updateLoginUsers', users); var msg = client.user + 'さんがログインしました!'; for(var key in messages) { client.emit('res', messages[key]['user'], messages[key]['msg']); } messages.push({'user':'system', 'msg' :msg}); io.sockets.emit('res', 'system', msg); }); // メッセージを受けたときの処理 client.on('chat', function(from, msg) { console.log("メッセージを送信しました。(from=" + from + ", msg=" + msg + ")"); messages.push({'user':from, 'msg' :msg}); // つながっているクライアント全員に送信 io.sockets.emit('res', from, msg); }); // クライアントが切断したときの処理 client.on('disconnect', function(){ console.log(client.sessionId + 'が切断しました。'); delete users[client.user]; io.sockets.emit('updateLoginUsers', users); var msg = client.user + 'さんがログアウトしました...'; io.sockets.emit('res', 'system', msg); messages.push({'user':'system', 'msg' :msg}); }); };
ここまで来たら以下のようにリアルタイムチャットができるようになっているはずです。
ポイントは、socket.on や socket.emit や client.on や io.sockets.emitの部分ですね。
コードが貼りつけられていて、よくわからないor動かないという方は、
https://github.com/akira-kuriyama/chatroom-websocket
にソースをまるごと上げたのでREADME.txtを読んでやってみてください。
(ただし、nodeやnpmがインストールされている前提です。)
なお、socket.ioを使用したチャット自体のサンプルは、
socket.io自体にも存在し、socket.io/examples/chat/ にあるので、そいつを参考にするとよいと思います。