8

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

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

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

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

但:

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

怎么做到呢 ?

4

3 回答 3

18

回答您的问题:

  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 服务器(只需传递某种标志)。

于 2013-09-03T15:21:47.103 回答
1

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

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

如果您不想在某些页面上连接 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 子句,用于或不将 javascript 文件包含在您的 socket.io 逻辑中。

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

socket.on('connect', function () {
    socket.emit('from', {page: 'your-page'});
});
于 2013-09-03T15:24:47.330 回答
0

如果您不选择有选择地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对象。

于 2013-09-03T14:55:14.893 回答