Node.js sample application with Socket.IO
Revision | 491df883272baa8279eafd5ea90bc7b980bfc5b2 (tree) |
---|---|
Time | 2012-12-09 22:26:36 |
Author | hylom <hylom@hylo...> |
Commiter | hylom |
separate socket.io routines from app.js to sockets/chat.js
@@ -3,14 +3,13 @@ | ||
3 | 3 | * Module dependencies. |
4 | 4 | */ |
5 | 5 | |
6 | -var express = require('express') | |
7 | - , routes = require('./routes') | |
8 | - , http = require('http') | |
9 | - , path = require('path') | |
10 | - , socketIO = require('socket.io'); | |
6 | +var express = require('express'); | |
7 | +var routes = require('./routes') | |
8 | +var http = require('http'); | |
9 | +var path = require('path'); | |
10 | +var chatsockets = require('./sockets/chat.js'); | |
11 | 11 | |
12 | 12 | var app = express(); |
13 | -var crypto = require('crypto'); | |
14 | 13 | |
15 | 14 | app.configure(function(){ |
16 | 15 | app.set('port', process.env.PORT || 3000); |
@@ -32,172 +31,11 @@ app.get('/', routes.index); | ||
32 | 31 | app.post('/room', routes.room); |
33 | 32 | |
34 | 33 | var server = http.createServer(app); |
35 | -var io = socketIO.listen(server, {log:false}); | |
34 | +var io = require('socket.io').listen(server, {log:false}); | |
36 | 35 | |
37 | 36 | server.listen(app.get('port'), function(){ |
38 | - console.log("Express server listening on port " + app.get('port')); | |
37 | + console.log('Express server listening on port ' + app.get('port')); | |
39 | 38 | }); |
40 | 39 | |
41 | -// socket.ioのソケットを管理するオブジェクト | |
42 | -var socketsOf = {}; | |
43 | - | |
44 | -// 指定したroomIdに属するクライアントすべてに対しイベントを送信する | |
45 | -function emitToRoom(roomId, event, data, fn) { | |
46 | - if (socketsOf[roomId] === undefined) { | |
47 | - return; | |
48 | - } | |
49 | - var sockets = socketsOf[roomId]; | |
50 | - Object.keys(sockets).forEach(function (key) { | |
51 | - sockets[key].emit(event, data, fn); | |
52 | - }); | |
53 | -}; | |
54 | - | |
55 | 40 | // socket.ioのコネクション設定 |
56 | -io.sockets.on('connection', function (socket) { | |
57 | - | |
58 | - // コネクションが確立されたら'connected'メッセージを送信する | |
59 | - socket.emit('connected', {}); | |
60 | - | |
61 | - // 認証情報を確認する | |
62 | - socket.on('hash password', function (password, fn) { | |
63 | - var hashedPassword = ''; | |
64 | - var shasum = crypto.createHash('sha512'); | |
65 | - | |
66 | - if (password !== '') { | |
67 | - shasum.update('initialhash'); | |
68 | - shasum.update(password); | |
69 | - hashedPassword = shasum.digest('hex'); | |
70 | - } | |
71 | - fn(hashedPassword); | |
72 | - }); | |
73 | - | |
74 | - // 認証情報を確認する | |
75 | - socket.on('check credential', function (client) { | |
76 | - // クライアントはconnectedメッセージを受信したら、minichatオブジェクトを | |
77 | - // 引数にこのメッセージを送信する | |
78 | - | |
79 | - // 認証情報の確認 | |
80 | - if (client.mode == 'create') { | |
81 | - // modeが'create'の場合、すでに対応するroomIdのチャットルームがないか | |
82 | - // チェックする | |
83 | - if (socketsOf[client.roomId] !== undefined) { | |
84 | - socket.emit('room exists', {}); | |
85 | - return; | |
86 | - } | |
87 | - socketsOf[client.roomId] = {}; | |
88 | - } | |
89 | - | |
90 | - if (client.mode == 'enter') { | |
91 | - // 対応するroomIdのチャットルームの存在をチェックする | |
92 | - if (socketsOf[client.roomId] === undefined) { | |
93 | - socket.emit('invalid credential', {}); | |
94 | - return; | |
95 | - } | |
96 | - // ユーザー名がかぶっていないかチェックする | |
97 | - if (socketsOf[client.roomId][client.userName] !== undefined) { | |
98 | - socket.emit('userName exists', {}); | |
99 | - return; | |
100 | - } | |
101 | - } | |
102 | - | |
103 | - // ソケットにクライアントの情報をセットする | |
104 | - socket.set('client', client, function () { | |
105 | - socketsOf[client.roomId][client.userName] = socket; | |
106 | - if (client.userName) { | |
107 | - console.log('user ' + client.userName + '@' + client.roomId + ' connected'); | |
108 | - } | |
109 | - }); | |
110 | - | |
111 | - // 認証成功 | |
112 | - socket.emit('credential ok', {}); | |
113 | - | |
114 | - // 既存クライアントにメンバーの変更を通知する | |
115 | - var members = Object.keys(socketsOf[client.roomId]); | |
116 | - emitToRoom(client.roomId, 'update members', members); | |
117 | - | |
118 | - var shasum = crypto.createHash('sha1') | |
119 | - var message = { | |
120 | - from: 'システムメッセージ', | |
121 | - body: client.userName + 'さんが入室しました', | |
122 | - roomId: client.roomId | |
123 | - } | |
124 | - message.date = _formatDate(new Date()); | |
125 | - shasum.update('-' + message.roomId); | |
126 | - message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
127 | - emitToRoom(message.roomId, 'push message', message); | |
128 | - | |
129 | - }); | |
130 | - | |
131 | - // ソケットが切断された場合、ソケット一覧からソケットを削除する | |
132 | - socket.on('disconnect', function () { | |
133 | - socket.get('client', function (err, client) { | |
134 | - if (err || !client) { | |
135 | - return; | |
136 | - } | |
137 | - var sockets = socketsOf[client.roomId]; | |
138 | - if(sockets !== undefined) { | |
139 | - delete sockets[client.userName]; | |
140 | - } | |
141 | - console.log('user ' + client.userName + '@' + client.roomId + ' disconnected'); | |
142 | - var members = Object.keys(sockets); | |
143 | - if (members.length === 0) { | |
144 | - delete socketsOf[client.roomId]; | |
145 | - } else { | |
146 | - // 既存クライアントにメンバーの変更を通知する | |
147 | - emitToRoom(client.roomId, 'update members', members); | |
148 | - var message = { | |
149 | - from: 'システムメッセージ', | |
150 | - body: client.userName + 'さんが退室しました', | |
151 | - roomId: client.roomId | |
152 | - } | |
153 | - var shasum = crypto.createHash('sha1') | |
154 | - message.date = _formatDate(new Date()); | |
155 | - shasum.update('-' + message.roomId); | |
156 | - message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
157 | - emitToRoom(message.roomId, 'push message', message); | |
158 | - | |
159 | - } | |
160 | - }); | |
161 | - }); | |
162 | - | |
163 | - // クライアントは'say'メッセージとともにチャットメッセージを送信する | |
164 | - socket.on('say', function (message, fn) { | |
165 | - console.log('receive message'); | |
166 | - | |
167 | - var shasum = crypto.createHash('sha1') | |
168 | - message.date = _formatDate(new Date()); | |
169 | - shasum.update(message.userName + '-' + message.roomId); | |
170 | - message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
171 | - emitToRoom(message.roomId, 'push message', message); | |
172 | - // クライアント側のコールバックを実行する | |
173 | - fn(); | |
174 | - }); | |
175 | - | |
176 | - // クライアントはログが必要な場合'request log'メッセージを送信する | |
177 | - socket.on('request log', function (data) { | |
178 | - socket.get('client', function (err, client) { | |
179 | - if (err || client === undefined) { | |
180 | - return; | |
181 | - } | |
182 | - emitToRoom(client.roomId, 'request log', {}, function (log) { | |
183 | - socket.emit('update log', log); | |
184 | - }); | |
185 | - }); | |
186 | - }); | |
187 | - | |
188 | -}); | |
189 | - | |
190 | -function _formatDate(date) { | |
191 | - var mm = date.getMonth(); | |
192 | - var dd = date.getDate(); | |
193 | - var HH = date.getHours(); | |
194 | - var MM = date.getMinutes(); | |
195 | - if (HH < 10) { | |
196 | - HH = '0' + HH; | |
197 | - } | |
198 | - if (MM < 10) { | |
199 | - MM = '0' + MM; | |
200 | - } | |
201 | - return mm + '/' + dd + ' ' + HH + ':' + MM; | |
202 | -}; | |
203 | - | |
41 | +io.sockets.on('connection', chatsockets.onConnection); |
@@ -1,4 +0,0 @@ | ||
1 | -// minichat.js | |
2 | - | |
3 | -(function () { | |
4 | -}).apply(this); |
@@ -0,0 +1,166 @@ | ||
1 | +var crypto = require('crypto'); | |
2 | + | |
3 | +// 指定したroomIdに属するクライアントすべてに対しイベントを送信する | |
4 | +function emitToRoom(roomId, event, data, fn) { | |
5 | + if (socketsOf[roomId] === undefined) { | |
6 | + return; | |
7 | + } | |
8 | + var sockets = socketsOf[roomId]; | |
9 | + Object.keys(sockets).forEach(function (key) { | |
10 | + sockets[key].emit(event, data, fn); | |
11 | + }); | |
12 | +}; | |
13 | + | |
14 | +// Dateオブジェクトから日時を表す文字列を生成する | |
15 | +function _formatDate(date) { | |
16 | + var mm = date.getMonth(); | |
17 | + var dd = date.getDate(); | |
18 | + var HH = date.getHours(); | |
19 | + var MM = date.getMinutes(); | |
20 | + if (HH < 10) { | |
21 | + HH = '0' + HH; | |
22 | + } | |
23 | + if (MM < 10) { | |
24 | + MM = '0' + MM; | |
25 | + } | |
26 | + return mm + '/' + dd + ' ' + HH + ':' + MM; | |
27 | +}; | |
28 | + | |
29 | +// socket.ioのソケットを管理するオブジェクト | |
30 | +var socketsOf = {}; | |
31 | + | |
32 | +// socket.ioのコネクション設定 | |
33 | +exports.onConnection = function (socket) { | |
34 | + | |
35 | + // コネクションが確立されたら'connected'メッセージを送信する | |
36 | + socket.emit('connected', {}); | |
37 | + | |
38 | + // 認証情報を確認する | |
39 | + socket.on('hash password', function (password, fn) { | |
40 | + var hashedPassword = ''; | |
41 | + var shasum = crypto.createHash('sha512'); | |
42 | + | |
43 | + if (password !== '') { | |
44 | + shasum.update('initialhash'); | |
45 | + shasum.update(password); | |
46 | + hashedPassword = shasum.digest('hex'); | |
47 | + } | |
48 | + fn(hashedPassword); | |
49 | + }); | |
50 | + | |
51 | + // 認証情報を確認する | |
52 | + socket.on('check credential', function (client) { | |
53 | + // クライアントはconnectedメッセージを受信したら、 | |
54 | + // minichatオブジェクトを引数にこのメッセージを送信する | |
55 | + | |
56 | + // 認証情報の確認 | |
57 | + if (client.mode == 'create') { | |
58 | + // modeが'create'の場合、すでに対応するroomIdのチャットルームがないか | |
59 | + // チェックする | |
60 | + if (socketsOf[client.roomId] !== undefined) { | |
61 | + socket.emit('room exists', {}); | |
62 | + return; | |
63 | + } | |
64 | + socketsOf[client.roomId] = {}; | |
65 | + } | |
66 | + | |
67 | + if (client.mode == 'enter') { | |
68 | + // 対応するroomIdのチャットルームの存在をチェックする | |
69 | + if (socketsOf[client.roomId] === undefined) { | |
70 | + socket.emit('invalid credential', {}); | |
71 | + return; | |
72 | + } | |
73 | + // ユーザー名がかぶっていないかチェックする | |
74 | + if (socketsOf[client.roomId][client.userName] !== undefined) { | |
75 | + socket.emit('userName exists', {}); | |
76 | + return; | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + // ソケットにクライアントの情報をセットする | |
81 | + socket.set('client', client, function () { | |
82 | + socketsOf[client.roomId][client.userName] = socket; | |
83 | + if (client.userName) { | |
84 | + console.log('user ' + client.userName + '@' + client.roomId + ' connected'); | |
85 | + } | |
86 | + }); | |
87 | + | |
88 | + // 認証成功 | |
89 | + socket.emit('credential ok', {}); | |
90 | + | |
91 | + // 既存クライアントにメンバーの変更を通知する | |
92 | + var members = Object.keys(socketsOf[client.roomId]); | |
93 | + emitToRoom(client.roomId, 'update members', members); | |
94 | + | |
95 | + var shasum = crypto.createHash('sha1') | |
96 | + var message = { | |
97 | + from: 'システムメッセージ', | |
98 | + body: client.userName + 'さんが入室しました', | |
99 | + roomId: client.roomId | |
100 | + } | |
101 | + message.date = _formatDate(new Date()); | |
102 | + shasum.update('-' + message.roomId); | |
103 | + message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
104 | + emitToRoom(message.roomId, 'push message', message); | |
105 | + | |
106 | + }); | |
107 | + | |
108 | + // ソケットが切断された場合、ソケット一覧からソケットを削除する | |
109 | + socket.on('disconnect', function () { | |
110 | + socket.get('client', function (err, client) { | |
111 | + if (err || !client) { | |
112 | + return; | |
113 | + } | |
114 | + var sockets = socketsOf[client.roomId]; | |
115 | + if(sockets !== undefined) { | |
116 | + delete sockets[client.userName]; | |
117 | + } | |
118 | + console.log('user ' + client.userName + '@' + client.roomId + ' disconnected'); | |
119 | + var members = Object.keys(sockets); | |
120 | + if (members.length === 0) { | |
121 | + delete socketsOf[client.roomId]; | |
122 | + } else { | |
123 | + // 既存クライアントにメンバーの変更を通知する | |
124 | + emitToRoom(client.roomId, 'update members', members); | |
125 | + var message = { | |
126 | + from: 'システムメッセージ', | |
127 | + body: client.userName + 'さんが退室しました', | |
128 | + roomId: client.roomId | |
129 | + } | |
130 | + var shasum = crypto.createHash('sha1') | |
131 | + message.date = _formatDate(new Date()); | |
132 | + shasum.update('-' + message.roomId); | |
133 | + message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
134 | + emitToRoom(message.roomId, 'push message', message); | |
135 | + | |
136 | + } | |
137 | + }); | |
138 | + }); | |
139 | + | |
140 | + // クライアントは'say'メッセージとともにチャットメッセージを送信する | |
141 | + socket.on('say', function (message, fn) { | |
142 | + console.log('receive message'); | |
143 | + | |
144 | + var shasum = crypto.createHash('sha1') | |
145 | + message.date = _formatDate(new Date()); | |
146 | + shasum.update(message.userName + '-' + message.roomId); | |
147 | + message.id = (new Date()).getTime() + '-' + shasum.digest('hex'); | |
148 | + emitToRoom(message.roomId, 'push message', message); | |
149 | + // クライアント側のコールバックを実行する | |
150 | + fn(); | |
151 | + }); | |
152 | + | |
153 | + // クライアントはログが必要な場合'request log'メッセージを送信する | |
154 | + socket.on('request log', function (data) { | |
155 | + socket.get('client', function (err, client) { | |
156 | + if (err || client === undefined) { | |
157 | + return; | |
158 | + } | |
159 | + emitToRoom(client.roomId, 'request log', {}, function (log) { | |
160 | + socket.emit('update log', log); | |
161 | + }); | |
162 | + }); | |
163 | + }); | |
164 | + | |
165 | +}; | |
166 | + |
@@ -5,7 +5,6 @@ html | ||
5 | 5 | link(rel='stylesheet', href='/css/style.css') |
6 | 6 | link(rel='stylesheet', href='/css/bootstrap.css') |
7 | 7 | script(src='/js/jquery-1.8.2.min.js') |
8 | - script(src='/js/minichat.js') | |
9 | 8 | script(src='/js/bootstrap.min.js') |
10 | 9 | script(src='/socket.io/socket.io.js') |
11 | 10 | body |
@@ -15,15 +15,12 @@ block content | ||
15 | 15 | .container |
16 | 16 | a.brand(href='/') minichat |
17 | 17 | ul.nav |
18 | - li | |
19 | - a ルーム名:#{room.name} | |
20 | - li | |
21 | - a(href='/') 退出する | |
18 | + li: a ルーム名:#{room.name} | |
19 | + li: a(href='/') 退出する | |
22 | 20 | #main-contents.container |
23 | 21 | .row |
24 | 22 | .span4 |
25 | - h3 | |
26 | - span#yourname #{user.name} | |
23 | + h3: span#yourname #{user.name} | |
27 | 24 | form |
28 | 25 | label |
29 | 26 | textarea#message.span4(rows='5', placeholder='メッセージを入力...') |
@@ -59,7 +56,6 @@ block content | ||
59 | 56 | |
60 | 57 | .modal-footer |
61 | 58 | a(href='/') トップページへ戻る |
62 | - | |
63 | 59 | |
64 | 60 | hr |
65 | 61 | footer |