Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tokunami/4486e6c01752fad14f30 to your computer and use it in GitHub Desktop.
Save tokunami/4486e6c01752fad14f30 to your computer and use it in GitHub Desktop.
$(function(){
var socket = io.connect(); //クライアントがソケット接続を要求
//接続確認
socket.on('connect',function(){ //サーバーがクライアントとの接続を確認すると、クライアントで'connect'イベントが発生
socket.on('count', function(data){
$('#count').text(data);
});
//メッセージを受信
socket.on('msg push', function(msg){ //クライアントで'msg push'イベントが発生し、コールバック
$('#img').attr("src", msg.text);
$('#imgtitle').html(msg.text);
$('#list').prepend($("<dt>" + new Date() + "</dt><p>" + msg.name + ":" + msg.text + "</p><hr>"));
});
});
//メッセージを送信
$('#comment_form').on('submit',function(){ //'comment form'から'submit'がリクエストされたとき
var name = $('#name').val();
var text = $('#text').val();
if(text && name){
socket.emit('msg post',{name: name, text: text}); //クライアントが'msg post'イベントを発火して{name, text}を送信
$('#text').val(''); //フォームを空欄にする
};
});
//サーバーに入るルーム名を送信
$('#room_form').on('submit', function(){ //'room form'から'submit'がリクエストされたとき
var num = $("#enter").val();
socket.emit("enter", {value: num}); //クライアントが'enter'イベントを発火してnumを送信
socket.on("roomList", function(roomList){ //クライアントで'roomList'イベントが発生し、コールバック
$("#list-box").text("");
if(roomList){
for(var j in roomList){
$("#list-box").append("ルーム『"+ j + "』に" + roomList[j] +"人います<br>");
}
}
});
socket.on("roomDel",function(roomList){
$("#list-box").text("");
if(roomList){
for(var k in roomList){
$("#list-box").append(k);
}
}
});
});
});
doctype html
html
head
meta(charset="utf-8")
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
p 現在の閲覧者数は
span#count
人です
div#list-box
br
form#room_form(action="javascript:void(0);" method="get" onsubmit="return false;")
input#enter(type="text" name="enter")
input(type="submit" value="ルームへ")
form#comment_form(action="javascript:void(0);" autocomplete="off")
p 名前:
input#name(type="text")
p メッセージ:
input#text(type="text")
input(type="submit" value="送信")
hr
image#img(src='http://localhost:3000/top')
p#imgtitle
hr
dl#list

####Node.js + express + socket.io で画像を返すチャットルーム

socket.io のRoom機能
  • 参考URL

https://github.com/Jxck/socket.io/wiki/Rooms

しくみ
  1. roomListというオブジェクトを作っておく。
  2. クライアント側からルーム名が送信される
  3. roomListに同一のルーム名がある場合→入室し人数を+1、ない場合→ルームを作成(サーバー側で振り分け)
  4. チャットはsetされたルームへ送信
  5. 退出時、ルーム人数が0になればroomListから削除
サーバーサイド
  • 3 roomListに同一のルーム名があるかないかで振り分け
var count = 0; //接続人数
var roomList = new Object();  

io.sockets.on('connection', function(socket) {
  count++;  //接続人数をインクリメント
  io.sockets.emit('count', count);  

  if(roomList){
    io.sockets.emit('roomList',roomList);
  }
  //ルームが作られていればクライアントを更新
  
  function upDateRL(roomList){
    if (roomList){
      io.sockets.emit('roomList', roomList);  
    }
  }

  socket.on("enter", function(data2){
    var data2name = data2.value;
    
    if(!roomList[data2name]){

      roomList[data2name] =1;

      socket.set('room', data2name);  
      socket.join(data2name); 

      io.sockets.emit("roomList", roomList);
    //ルーム名がroomListにない場合→ルーム作成


    }else if(roomList[data2name]){
      if(roomList[data2name] >= 1){
        roomList[data2name]++;
        
        socket.set('room', data2name);
        socket.join(data2name);

        io.sockets.to(data2name).emit('message', data2name + "に入室しました。")

        upDateRL(roomList); //上で定義した関数

      }
    }
    //ルーム名がroomListにある場合は入室

    
  });
  • 4 チャットはsetされたルームへ送信
  socket.on('msg post', function(msg) {

    var room;
    socket.get('room', function(err, _room){  //ここがよくわからない① 調べる
      room = _room;
    });

    io.sockets.to(room).emit('msg push', {name: msg.name, text: msg.text});

  });
  • 5 退出時、ルーム人数が0になればroomListから削除
  socket.on('disconnect', function(){
    count--;
    var room;

    io.sockets.emit('count', count);

    socket.get('room', function(err, _room){  //ここの意味がよくわからない①
      room = _room;
    });
    if(room){
      roomList[room]--;
      socket.leave(room);

      if(roomList[room] < 1){ 
        delete roomList[room];
        io.sockets.emit("roomDel", roomList);
      //参加人数が0人の場合、roomListから部屋を削除
      
      }else{
        io.sockets.to(room).emit('message', room + "を退室しました");
        upDateRL(roomList); //上で定義した関数
      }
    }

  });
  
クライアントサイド
  $('#room_form').on('submit', function(){  //id = room_formのsubumitがリクエストされたとき
    var num = $("#enter").val();
    socket.emit("enter", {value: num});   //クライアント側からルーム名送信

    socket.on("roomList", function(roomList){
      $("#list-box").text("");
      if(roomList){
        for(var j in roomList){
          $("#list-box").append("ルーム『"+ j + "』に" + roomList[j] +"人います<br>");  //listbox(roomlistを表示)書き換え
        }
      }
    });

    socket.on("roomDel",function(roomList){ //ここの意味がよくわからない② 調べる
      $("#list-box").text("");
      if(roomList){
        for(var k in roomList){
          $("#list-box").append(k);
        }
      }
    });
  });
  • 動作確認はできたが、意味がわからない箇所がいくつかあるので調べたりコメントアウトしてみたりして内容を確認する。
  • 同様に、不要と思われる部分もあるので確認する。
  • いったんルームAに入室し、切断せずにルームBに入室したときにlistboxに反映されない不具合。

(接続はルームBにされているので、チャットは問題なく動作する)

  • だいぶ長い。
  • もう少し精査します。
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, io = require('socket.io');
var fs = require('fs');
var app = express();
var server = http.createServer(app);
var io = io.listen(server);
var IMAGE_DIR = './public/images/'; //イメージファイルを格納しているディレクトリ
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', function(req,res){
res.render('index.jade',{
title: 'ChatRoom'
});
});
app.get('/top', function(req, res){
fs.readFile('./public/images/noimage.jpg', function(err, data){
res.set('Content-Type', 'image/jpeg');
res.send(data);
});
});
app.get('/:msg', function(req, res){
if(typeof req.params.msg === 'undefined'){
res.send(400);
return;
//エラー処理 msgの型が判別できない場合はエラーを返して終了
}
fs.readFile(path.join(IMAGE_DIR , req.params.msg + '.jpg'), function(err, data){
if(err){
console.error(err);
res.send(500);
return;
}
//エラー処理 IMAGE_DIRにリクエストされたjpgがない場合はエラーを返して終了
res.set('Content-Type', 'image/jpeg');
res.send(data);
});
});
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
var count = 0;
var roomList = new Object();
io.sockets.on('connection', function(socket) { //サーバーがクライアントとの接続を確立し、connectionイベント発生
console.log("connected");
count++;
io.sockets.emit('count', count);
if(roomList){
io.sockets.emit('roomList',roomList);
}
//ルームが新規作成されていればクライアント側を更新する
function upDateRL(roomList){
if (roomList){
io.sockets.emit('roomList', roomList); //サーバーが'roomList'イベントを発火し、'roomList'を送り返す&ブロードキャスト
}
}
socket.on("enter", function(data2){
var data2name = data2.value
if(!roomList[data2name]){
roomList[data2name] =1;
console.log(data2name + "ルームが作られました。" + roomList[data2name] + "人います。");
socket.set('room', data2name);
socket.join(data2name);
io.sockets.to(data2name).emit('message', data2name + "に入室しました");
io.sockets.emit("roomList", roomList); //サーバーが'roomList'イベントを発火し、'roomList'を送り返す&ブロードキャスト
//roomListにルーム名がない場合、作成して入室
}else if(roomList[data2name]){
if(roomList[data2name] >= 1){
roomList[data2name]++;
console.log(data2name + "ルームに入室しました。現在" + roomList[data2name] + "人います。");
socket.set('room', data2name);
socket.join(data2name);
io.sockets.to(data2name).emit('message', data2name + "に入室しました。")
upDateRL(roomList); //上で定義した'roomList'を更新する関数
}
}
//roomListにルーム名がある場合、そこに入室
});
socket.on('msg post', function(msg) { //サーバーで'msg post'イベントが発生し、コールバック
console.log(msg);
var room;
socket.get('room', function(err, _room){
room = _room;
});
io.sockets.to(room).emit('msg push', {name: msg.name, text: msg.text}); //サーバーが'msg push'イベントを発火し、'msg'を送り返す&ブロードキャスト
console.log("message send room" + room + ", " + msg);
});
//disconnectの処理
socket.on('disconnect', function(){
count--;
var room;
io.sockets.emit('count', count);
socket.get('room', function(err, _room){
room = _room;
});
if(room){
roomList[room]--;
socket.leave(room);
if(roomList[room] < 1){
console.log(room + "was deleted");
delete roomList[room];
console.log(roomList);
io.sockets.emit("roomDel", roomList);
}else{
console.log(room + "人数" +roomList[room]);
io.sockets.to(room).emit('message', room + "を退室しました");
upDateRL(roomList); //上で定義した'roomList'を更新する関数
}
}
});
});
@stoshiya
Copy link

server.jsにいくつか落とし穴があるように思えます.伊東さんも交えてコードリーディングしながら,レビューした方が良いでしょうかね?

@tokunami
Copy link
Author

レビューぜひお願いします。
空いている時間に設定しますので、よろしくお願いいたします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment