【问题标题】:How to use socket.io only on specific page in my website?如何仅在我网站的特定页面上使用 socket.io?
【发布时间】:2013-09-04 08:59:35
【问题描述】:

假设我有一个网站在主页上不需要 web-sockets,但在其他一些相对路径上需要它(例如“/new”)。

假设我需要“连接”事件来计算登录到“主页”页面和“新”页面的用户。

我尝试在相对路径中配置 socket.io 'connection' 事件,例如:

app.get('/new',
         function(req,res) {
              io.sockets.on('connection', function (socket) {
                .....
              }
         });

但是:

  1. 表现不佳。当很多用户连接时,该事件会在不应该发生的时候引发。
  2. 我没有在网上看到任何像上面这样的例子。所有 socket.io 事件都在主文件 (app.js) 中配置一次。

怎么做?

【问题讨论】:

  • 仅仅为了响应 express /new 路由而包含 socket.io 客户端脚本怎么样?然后只有在访问 /new 时才建立连接
  • 但如果我需要对两个页面使用“连接”,它将无法工作
  • 好的,我想我明白了……您想统计特定页面上的活跃用户数吗?
  • 这只是我给出的例子。我真正想要的是在两个不同的页面上使用“连接”事件。
  • 是的,我做到了。只需在访问者首次请求 /new 页面时初始化(交付 socket.io 用户脚本)套接字并将其存储在 cookie 中。当他访问任何其他页面时,您可以读取 cookie 并在必要时重新创建套接字。您连接到 socket.io 的连接接口默认是 yourdomain.tld/socket.io/

标签: node.js socket.io


【解决方案1】:

回答您的问题:

  1. 很明显,因为当用户点击/new 时,它的处理程序会触发并将连接处理程序添加到io。这是一个巨大的内存泄漏。

  2. 这与上述有关。您不想在用户每次点击/new时添加连接处理程序。

现在要解决您的问题,我认为最好的办法是调用(在浏览器端)

io.connect("http://localhost/new");

然后在您的 Node.js 应用程序中:

io.of("/new").on("connection", function (socket) {
    // here are connections from /new
});

代码应该放在顶层,而不是在路由处理程序中。如果您希望它更具动态性,那么您可以创建自己的子协议:

  1. 连接io服务器:io.connect("http://localhost);
  2. 发消息I'm in /new;
  3. 在服务器上获取该消息并将该连接存储在适当的列表中。

当然,您可以在路由处理程序中指定是否希望您的客户端连接到 socket.io 服务器(只需传递某种标志)。

【讨论】:

  • 1.你能解释更多关于第二个选项的信息吗?也许分享一些代码? 2. 'of' 是保留字吗?
【解决方案2】:

Socket.io 连接未在您的处理程序方法中像那样初始化。
它将在页面呈现后初始化,浏览器加载客户端脚本并调用 io.connect (在您的客户端脚本中)。

在服务器端脚本中的任何位置调用 io.sockets.on('connection') 只需将另一个侦听器(服务器侦听器)注册到套接字连接事件。
将它放在请求处理程序中意味着无论何时您向“/new”发送 GET 请求,都会注册另一个侦听器。 (你可以放一些console.log,点击刷新几次,看看什么时候有新的socket连接)

如果你不想在某些页面上连接socket.io,你可以这样做

在您的服务器端脚本上

app.all("*", function(req, res, next) {
    res.locals({
        needSocketIo: true
    });
}

app.get('/some-page-you-do-not-want-socket-io', function(req, res) {
    res.render('some-view', {needSocketIo: false});
})

在您的视图/布局上,它只是一个 if/else 子句,用于在您的 socket.io 逻辑中包含或不包含 javascript 文件。

如果你想让你的服务器知道套接字从哪里连接,你可以从客户端发出一些消息

socket.on('connect', function () {
    socket.emit('from', {page: 'your-page'});
});

【讨论】:

    【解决方案3】:

    如果您不选择在每个页面选择性地放置socket.io 客户端,那么您可以使用授权事件并检查它们从哪个页面连接:

    io.configure(function () {
      io.set('authorization', function (handshakeData, callback) {
        if (handshakeData.url == '/new') {
          //allow the socket to connect
          callback(null, true);
        } else {
          //prevent the socket handshake with an error
          callback('socket.io is not accepting connections from this page', false);
        }
      });
    });
    

    您不应该多次使用io.sockets.on 对象,因为在您的代码中,每次有人加载该页面时,您都会向connection 事件添加侦听器。此外,当握手被拒绝时,connection 事件永远不会被触发,因此您可以使用如下设置:

    io.sockets.on('connection', function(socket) {
      //this shouldn't ever happen, it's the same object that was checked before
      if (socket.handshake.url != '/new') {
        socket.disconnect();
        return;
      }
    
      //do something on page '/new'
    }
    
    app.get('/new', function(req, res) {
      //sockets can successfully connect with this page
    });
    
    app.get('/foo', function(req, res) {
      //sockets from this page will fail handshakes and be disconnected
    });
    

    如果您需要计算页面上的用户数量,您可以同时监听套接字的连接和断开事件。这是可以做到的一种方式:

    var pages = [];
    io.sockets.on('connection', function(socket) {
      if (pages[socket.handshake.url] == null) {
        pages[socket.handshake.url] = 0;
      }
      pages[socket.handshake.url]++;
    
      socket.on('disconnect', function() {
        pages[socket.handshake.url]--;
      });
    }
    

    如果人们打开了多个选项卡,那么您可以存储连接的会话 cookie 并查找匹配项,同样使用 socket.handshake 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 2013-09-05
      • 2017-03-06
      • 2015-08-30
      • 1970-01-01
      相关资源
      最近更新 更多