socket.io 概述

2018-10-18 11:01 更新

如何使用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 允许触发和相应自定义事件。 除了 connectmessagedisconnect 之外,你还可以触发自定义事件:

服务端


// 提示: 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>
      

广播消息


要广播消息,只需要在 emitsend 方法前面加上 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 用的也是它。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号