socket.io 概述
如何使用socket.io
安装
$ npm install socket.io
使用 Node http 服务器
服务端 (app.js)
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
客户端 (index.html)
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
使用 Express 3/4
服务端 (app.js)
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
客户端 (index.html)
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
使用 Express 2.x
服务端 (app.js)
var app = require('express').createServer();
var io = require('socket.io')(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
客户端 (index.html)
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
发送和接收事件
Socket.IO 允许触发和相应自定义事件。 除了 connect
、 message
和 disconnect
之外,你还可以触发自定义事件:
服务端
// 提示: io(<port>) 会自动创建 http 服务器
var io = require('socket.io')(80);
io.on('connection', function (socket) {
io.emit('this', { will: 'be received by everyone'});
socket.on('private message', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
});
socket.on('disconnect', function () {
io.emit('user disconnected');
});
});
指定命名空间
如果你可以控制应用中的所有消息和事件,使用默认的 / 命名空间就够了。但如果你使用了第三方代码,或是要将代码分享给其他人使用, socket.io 还可以为 socket 提供命名空间。
这样就可以 复用
单个连接。 下面的例子中, socket.io 只用了一个 WebSocket
连接,而不是两个。
服务端 (app.js)
var io = require('socket.io')(80);
var chat = io
.of('/chat')
.on('connection', function (socket) {
socket.emit('a message', {
that: 'only'
, '/chat': 'will get'
});
chat.emit('a message', {
everyone: 'in'
, '/chat': 'will get'
});
});
var news = io
.of('/news')
.on('connection', function (socket) {
socket.emit('item', { news: 'item' });
});
客户端 (index.html)
<script>
var chat = io.connect('http://localhost/chat')
, news = io.connect('http://localhost/news');
chat.on('connect', function () {
chat.emit('hi!');
});
news.on('news', function () {
news.emit('woot');
});
</script>
发送不稳定消息(可能丢失的消息)
有时一些消息可能会丢失。假定你要做一款应用,用于显示实时的包含关键词 bieber
的推文。
如果客户端还不能接收消息 (由于网络较慢或者其他问题,或者是使用长连接方式连接,且正处于请求-响应循环中),但是不能接收所有的关于 bieber 的推文并不会严重影响你的应用。
这种情况下,你可以将这些消息作为不稳定消息发送。
服务端
var io = require('socket.io')(80);
io.on('connection', function (socket) {
var tweets = setInterval(function () {
getBieberTweet(function (tweet) {
socket.volatile.emit('bieber tweet', tweet);
});
}, 100);
socket.on('disconnect', function () {
clearInterval(tweets);
});
});
发送并获取数据(回执)
有时,你需要在客户端确认消息已接收后执行一个回调。
要做到这一点,只需要为 .send
或 .emit
方法的最后一个参数传入一个函数即可。 更重要的是,当你使用 .emit
方法时,确认是由您完成的,这意味着您也可以传递数据:
服务端 (app.js)
// 注意:这里的示例加入了译者自己的理解,如果觉得不通,可以查看官网示例
// 流程应该是这样的:
// 1.客户端触发了 'ferret' 事件,发送数据 'tobi' 给服务器,
// 并注册了一个回调 function(data){...} 以等待服务端的回执(acknowledgement)
// 2.服务端响应 'ferret' 事件,并在适当的时候调用 cb() ,为客户端返回回执,
// 这里的 'woot' 可有可无,如果没有,那么客户端回调中的 data 就是 undefined
// 3.客户端收到回执 ,执行预先注册的回调 function(data){...}
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('ferret', function (name, cb) {
console.log(name); // name 将会是 'tobi'
// 这里的回调 cb() 在服务器接收到消息后可以调用,以通知客户端服务器已接收消息;
// 调用时还可以返回数据给客户端(这里是 'woot')
cb('woot');
});
});
客户端 (index.html)
<script>
// 注意:这里的示例加入了译者自己的理解,如果觉得不通,可以查看官网示例
var socket = io(); // TIP: io() 不带参数会开启自动发现
socket.on('connect', function () { // TIP: 你也可以直接监听具体事件,而不用监听 `connect` 事件!
socket.emit('ferret', 'tobi', function (data) {
// 回调将在服务器端调用 cb() 后执行
console.log(data); // data 将会是 'woot'
});
});
</script>
广播消息
要广播消息,只需要在 emit
和 send
方法前面加上 broadcast
标志即可。广播意味着将消息发送给除发送者以外的所有人。
服务端
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.broadcast.emit('user connected');
});
用作跨浏览器的 WebSocket
如果要使用 WebSocket 的语法,只需要调用 send
方法并监听 message
事件即可:
服务端 (app.js)
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('message', function () { });
socket.on('disconnect', function () { });
});
客户端 (index.html)
<script>
var socket = io('http://localhost/');
socket.on('connect', function () {
socket.send('hi');
socket.on('message', function (msg) {
// my msg
});
});
</script>
如果你不关心自动重连逻辑等问题, 可以看看 Engine.IO, 这是一个 WebSocket 语义的传输层。 Socket.IO 用的也是它。
更多建议: