最近学习了socket.io房间的用法,现在来梳理一下。
首先我们还是先看下客户端的chat.html,这取自于官方文档的例子:
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font: 13px Helvetica, Arial;
}
form {
background: #000;
padding: 3px;
position: fixed;
bottom: 0;
width: 100%;
}
form input {
border: 0;
padding: 10px;
width: 90%;
margin-right: .5%;
}
form button {
width: 9%;
background: rgb(130, 224, 255);
border: none;
padding: 10px;
}
#messages {
list-style-type: none;
margin: 0;
padding: 0;
}
#messages li {
padding: 5px 10px;
}
#messages li:nth-child(odd) {
background: #eee;
}
#messages {
margin-bottom: 40px
}
</style>
</head>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function () {
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function (msg) {
$('#messages').append($('<li>').text(msg));
});
});
</script>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>
怎样知道每个客户端只在自己的房间通信呢?
设计思路是只要新建一个客户端socket实例,就产生一个房间号。
如果用io.emit对该房间广播消息,那么只有此房间的socket可以收到,而非此房间的socket则收不到信息。
请看服务端代码:
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/chat.html');
});
var count = 0;
io.on('connection', function (socket) {
console.log('a user connected!');
var roomNum = 'room' + (++count);//自增实现socket进入不同房间
socket.join(roomNum, function () {
console.log(socket.rooms);
}); //加入房间后,打印出socket和room的信息
socket.on('chat message', function (msg) {
var room = Object.keys(socket.rooms)[1]; //这是当前socket的房间,这个对象设置得有点怪,但是事实如此。
io.to(room).emit('chat message', msg);
console.log(room);//打印出房间。
});
});
http.listen(3000, function () {
console.log('listening on *:3000');
});
打开两个客户端,客户端如图:
这时查看服务端控制台:
socket.rooms这个对象有点怪,居然是这样的结构:
[{socket.id: socket.id, roomNo.: roomNo.}]
我不知道为什么官方API要这么设定。
所以如果我们要获得当前socket.id的房间号,就必须这么写了:
var room = Object.keys(socket.rooms)[1];
现在我们在客户端输入一个”hello”.
服务器接收到以后,广播这个”hello”,所以在当前客户端可以看到。
服务器控制台显示这是room1
的消息
另外一个客户端则是一片空白,因为它是在room2里面。
现在我们把客户端的代码稍稍改下,让房间号固定,重新运行:
var roomNum = 'room' + count;
这时候我们能够看到服务端控制台显示两个客户端都属于room0
我们找任意一个客户端继续广播消息, 这时候就会看到两个客户端都接收到了消息。