- Node.js v0.11.11
- Express v3.5.2
- socket.io v0.9.16
- 画像を数枚準備 (今回は neko.jpg, inu.jpg, umi.jpeg, hana.jpg, fukuoka.jpg)
$ sudo npm install express@3
$ express chat_gazou
$ cd chat_gazou && npm install
$ npm install socket.io
なお、今回はnpm install
と npm install socket.io
を別個に実施したが、後から調べたところ、express
でchat_gazouを作成後、package.jsonにsocke.ioの項を書き加えてからnpm install
すると、socket.ioを別個にインストールする必要がない模様。
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.5.2",
"jade": "*"
"socket.io": "*"
}
}
- デフォルトでは app.js だが、今回はわかりやすくするためにserver.jsにファイル名を変更した。
- 変数の宣言を書き加える (これと書いてある行)
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var io = require('socket.io'); //これ socket.io インスタンスの作成
var fs = require('fs'); //これ ファイルシステムモジュールfsのインスタンス作成
var app = express();
var server = http.createServer(app); //これ
var io = io.listen(server); //これ
-
//all environments
は変更しない -
app.get('/', routes.index);
を書き換え
//ローカルを踏んだ時にindex.jadeをレンダリングする (titleは ChatRoooom)
app.get('/', function(req,res){
res.render('index.jade',{
title: 'ChatRoooom'
});
});
//localhost:3000/nekoにアクセスした時に neko.jpg を読み込んで送る
app.get('/neko', function(req, res){
fs.readFile('neko.jpg',function(err, data){ //neko.jpgを読み込み、function(err,data)の呼び出し
res.set('Content-Type', 'image/jpeg'); //ヘッダの指定 jpeg
res.send(data); //送信
});
});
//以下、nekoと同じ要領でinu、umi、hana、fukuokaを作る
app.get
の下に出てくるhttp.createServer(app)
は、すでにserver
として宣言しているので、書き換える
server.listen(app.get('port'), function(){
- 最後にsocketに関する部分を書き加える
io.sockets.on('connection', function(socket) { //サーバがクライアントとの接続を確立すると、サーバで 'connection'イベントが発生
socket.on('msg post', function(msg) { //サーバで 'msg post' イベントが発生し、コールバックが実行される
console.log(msg);
io.sockets.emit('msg push', msg); //サーバが 'msg push' イベントを発火して受信したメッセージを送ってきた本人とそれ以外のクライアントに送信
});
});
- 場所 chat_gazou > public > javascripts > client.js
$(function(){
var socket = io.connect('http://localhost/'); //クライアントが 'http://localhost' にソケット接続を要求
socket.on('connect',function(){ //サーバがクライアントとの接続を確立すると、クライアントで 'connect' イベントが発生
console.log('connected.');
});
$('#comment_form').on('submit',function(){
var msg = $('#comment').val();
socket.emit('msg post', msg); //クライアントが 'msg post' イベントを発火して文字列 'msg' を送信
$('#comment').val(''); //コメント欄の初期化
});
socket.on('msg push', function(msg){ //クライアントで 'msg push' イベントが発生し、コールバックが実行される
$('#img').attr("src", msg); //img srcの書き換え
$('#imgtitle').html(msg); //画像タイトルの書き換え
});
});
$
があたまについているのはjQuery- 全体を
$(function(){})
でくるむのは、htmlファイル内に記述されたDOM要素をすべて読み込んでから引数のfunctionを実行するようにするためのお作法。$(document).ready()
の省略形。
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
script(type='text/javascript', src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')
script(type='text/javascript', src='/socket.io/socket.io.js')
script(type='text/javascript', src='/javascripts/client.js')
body
h1= title
form(action="javascript:void(0);" id="comment_form")
label comment:
input(type="text" id="comment")
input(type="submit" value="送信")
hr
image(src='http://localhost:3000/umi' , id="img") //初期画面ではumi.jpgを表示
p(id="imgtitle")
hr
- index.jadeで指定したid
img
とimgtitle
をクライアント側で書き換えている(msg push
イベントが発生して実行されるコールバック関数)。
$ node server
- localhost:3000で動作確認。
-
listen関数について調べる。(var io が2回出てきていることに関して、2回めのio.listen(server)は結局何なのか)
-
事前に用意した画像の名前以外が打ち込まれた時の対処。
-
画像が表示されるのではなくダウンロードされる事態が発生し、てこずった。
res.send()
のところでヘッダ指定がうまくいっていなかったようで、公式HP記載のres.set()
で事前にヘッダを指定でき、解決した。ほかの諸問題も公式HPで解決できることが多かった。
次のソースコードを読むのがよいでしょう.
https://github.com/LearnBoost/socket.io/blob/0.9/lib/socket.io.js#L32-L79
41行目の function (....) は無名関数というもので,io.listen(server) の実際の処理が記載されています.この関数は最大3つの可変長パラメータをとりますが,処理の大部分はパラメータの数の違いに関する処理で,ポイントとなるのは78行目のみです.