如何使用socket.io
$ npm install socket.io
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);
});
});
<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>
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);
});
});
<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>
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);
});
});
<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 允許觸發(fā)和相應(yīng)自定義事件。 除了 connect
、 message
和 disconnect
之外,你還可以觸發(fā)自定義事件:
// 提示: io(<port>) 會自動創(chuàng)建 http 服務(wù)器
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');
});
});
如果你可以控制應(yīng)用中的所有消息和事件,使用默認(rèn)的 / 命名空間就夠了。但如果你使用了第三方代碼,或是要將代碼分享給其他人使用, socket.io 還可以為 socket 提供命名空間。
這樣就可以 復(fù)用
單個連接。 下面的例子中, socket.io 只用了一個 WebSocket
連接,而不是兩個。
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' });
});
<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>
有時一些消息可能會丟失。假定你要做一款應(yīng)用,用于顯示實時的包含關(guān)鍵詞 bieber
的推文。
如果客戶端還不能接收消息 (由于網(wǎng)絡(luò)較慢或者其他問題,或者是使用長連接方式連接,且正處于請求-響應(yīng)循環(huán)中),但是不能接收所有的關(guān)于 bieber 的推文并不會嚴(yán)重影響你的應(yīng)用。
這種情況下,你可以將這些消息作為不穩(wěn)定消息發(fā)送。
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);
});
});
有時,你需要在客戶端確認(rèn)消息已接收后執(zhí)行一個回調(diào)。
要做到這一點(diǎn),只需要為 .send
或 .emit
方法的最后一個參數(shù)傳入一個函數(shù)即可。 更重要的是,當(dāng)你使用 .emit
方法時,確認(rèn)是由您完成的,這意味著您也可以傳遞數(shù)據(jù):
// 注意:這里的示例加入了譯者自己的理解,如果覺得不通,可以查看官網(wǎng)示例
// 流程應(yīng)該是這樣的:
// 1.客戶端觸發(fā)了 'ferret' 事件,發(fā)送數(shù)據(jù) 'tobi' 給服務(wù)器,
// 并注冊了一個回調(diào) function(data){...} 以等待服務(wù)端的回執(zhí)(acknowledgement)
// 2.服務(wù)端響應(yīng) 'ferret' 事件,并在適當(dāng)?shù)臅r候調(diào)用 cb() ,為客戶端返回回執(zhí),
// 這里的 'woot' 可有可無,如果沒有,那么客戶端回調(diào)中的 data 就是 undefined
// 3.客戶端收到回執(zhí) ,執(zhí)行預(yù)先注冊的回調(diào) function(data){...}
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('ferret', function (name, cb) {
console.log(name); // name 將會是 'tobi'
// 這里的回調(diào) cb() 在服務(wù)器接收到消息后可以調(diào)用,以通知客戶端服務(wù)器已接收消息;
// 調(diào)用時還可以返回數(shù)據(jù)給客戶端(這里是 'woot')
cb('woot');
});
});
<script>
// 注意:這里的示例加入了譯者自己的理解,如果覺得不通,可以查看官網(wǎng)示例
var socket = io(); // TIP: io() 不帶參數(shù)會開啟自動發(fā)現(xiàn)
socket.on('connect', function () { // TIP: 你也可以直接監(jiān)聽具體事件,而不用監(jiān)聽 `connect` 事件!
socket.emit('ferret', 'tobi', function (data) {
// 回調(diào)將在服務(wù)器端調(diào)用 cb() 后執(zhí)行
console.log(data); // data 將會是 'woot'
});
});
</script>
要廣播消息,只需要在 emit
和 send
方法前面加上 broadcast
標(biāo)志即可。廣播意味著將消息發(fā)送給除發(fā)送者以外的所有人。
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.broadcast.emit('user connected');
});
如果要使用 WebSocket 的語法,只需要調(diào)用 send
方法并監(jiān)聽 message
事件即可:
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('message', function () { });
socket.on('disconnect', function () { });
});
<script>
var socket = io('http://localhost/');
socket.on('connect', function () {
socket.send('hi');
socket.on('message', function (msg) {
// my msg
});
});
</script>
如果你不關(guān)心自動重連邏輯等問題, 可以看看 Engine.IO, 這是一個 WebSocket 語義的傳輸層。 Socket.IO 用的也是它。
更多建議: