【问题标题】:How do I store persistent data with xhr-polling in Socket.IO?如何在 Socket.IO 中使用 xhr-polling 存储持久数据?
【发布时间】:2012-03-20 21:33:14
【问题描述】:

我正在使用 Node.js 和 Socket.IO 编写一个多房间聊天应用程序,我想知道当传输是 xhr-polling 时,如何处理需要在会话期间持续存在的数据。

目前,在客户端上,我正在发送连接时的“加入”事件,该事件传递了很长的几个变量(例如用户名),我使用 Socket.IO 的 get 和 set 方法将其存储在服务器端。然后它们一直可用,直到客户端断开连接。

如果传输是 Websockets,这可以正常工作,但如果它回退到 xhr-polling,则会在每次连接时发出 join 事件,该事件每 5-10 秒发生一次。 (类似地,“某某已离开/加入房间”在每个 xhr-poll 请求上发送,这也是不可取的。)

我不确定最好的前进方式是什么。我无法禁用 xhr-polling,因为它是无闪存 IE 的必要后备。

这里是相关的客户端代码:

socket.on("connect", function(){
    socket.emit("join", { username: username, room: room });
});

在服务器上:

var io = require("socket.io").listen(8124)
, buffer = {}
, max_room_buffer = 15;

io.sockets.on("connection", function(socket) {
    socket.on("join", function(data){
        if(data.username && data.room) {
        socket.set("data", data);
        socket.join(data.room);
        if(!buffer[data.room]) buffer[data.room] = [];
        socket.broadcast.to(data.room).emit("message", "<em>" + data.username + " has joined room " + data.room + "</em>");
        socket.emit("message", "<em>You have joined room " + data.room + "</em>");
        socket.emit("message", buffer[data.room]);
    }
});

socket.on("message", function(message) {
    if(message) {
        socket.get("data", function(err, data){
            if(data) {
                var msg = "<span>" + data.username + ":</span> " + message;
                buffer[data.room].push(msg);
                if(buffer[data.room].length > max_room_buffer) buffer[data.room].shift();
                io.sockets.in(data.room).emit("message", msg);
            }
        });
    }
});

socket.on("disconnect", function () {
    socket.get("data", function(err, data){
        if(data) {
            socket.leave(data.room);
            socket.broadcast.to(data.room).emit("message", "<em>" + data.username + " has left room " + data.room + "</em>");
        }
    });
});

});

提前致谢。

【问题讨论】:

  • 我认为 socket.io 本身不应该处理它而不是开发人员处理它.. 很奇怪。
  • 我猜像分块传输编码之类的东西,不确定是否支持“AJAX 多部分流”,不确定它是否相同
  • 我认为这一定是每个聊天应用程序在使用 socket.io 时都会遇到的问题,但我似乎在 Google 上找不到任何内容。处理这个问题可能有一个最佳实践,但我是 socket.io 的新手。

标签: javascript node.js chat socket.io


【解决方案1】:

也许我遗漏了一些东西,但这行不通。

客户:

var firstJoin = true;
socket.on("connect", function(){
    socket.emit("join", { username: username, room: room, firstJoin: firstJoin });
    firstJoin = false;
});

服务器:

io.sockets.on("connection", function(socket) {
    socket.on("join", function(data){
        if(data.username && data.room) {
        socket.set("data", data);
        socket.join(data.room);
        if(!buffer[data.room]) buffer[data.room] = [];

        if (data.firstJoin) {
            socket.broadcast.to(data.room).emit("message", "<em>" + data.username + " has joined room " + data.room + "</em>");
            socket.emit("message", "<em>You have joined room " + data.room + "</em>");
            socket.emit("message", buffer[data.room]);
        }
    }
});

至于每次新的轮询都会发生连接事件,这是 XHR 轮询不可避免的结果。由于每次轮询都是一个新的 HTTP 请求,因此之前的请求没有任何状态,因此需要重新设置。

如果您想减少这种情况发生的频率,您可以尝试将轮询持续时间从其默认值 20 增加。例如:

io.configure(function() {
    io.set('polling duration', 60);
});

【讨论】:

  • 看起来它可以解决一些问题。当用户真正断开连接时,我不得不在没有通知的情况下生活,除非有办法在客户端没有在一定时间内 ping 通的情况下触发事件?
  • 是的,这不是一个容易解决的问题。理论上断开连接事件应该在一段时间后触发(我认为默认的close timeout 是 25 秒),但可能会有延迟:stackoverflow.com/questions/6280569/…
  • 谢谢 Rohan,我会看看那个帖子。我很乐意为您的答案投票,但作为一个新用户,我还没有足够的声誉!
猜你喜欢
  • 2015-05-04
  • 2013-08-01
  • 2013-04-06
  • 2012-03-03
  • 2013-04-03
  • 1970-01-01
  • 2019-05-09
  • 2023-03-09
  • 2017-11-28
相关资源
最近更新 更多