如何在 Socket.IO 中使用 xhr-polling 存储持久数据?

Posted

技术标签:

【中文标题】如何在 Socket.IO 中使用 xhr-polling 存储持久数据?【英文标题】:How do I store persistent data with xhr-polling in Socket.IO? 【发布时间】: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 的新手。 【参考方案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 秒),但可能会有延迟:***.com/questions/6280569/… 谢谢 Rohan,我会看看那个帖子。我很乐意为您的答案投票,但作为一个新用户,我还没有足够的声誉!

以上是关于如何在 Socket.IO 中使用 xhr-polling 存储持久数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Socket.IO 中模拟连接失败

如何在控制器中使用 socket.io

Node.js 如何在快速路由中使用 socket.io

如何在 socket.io 1.0 中获取房间的客户列表

如何在socket.io中发射到房间? [复制]

如何在 android socket.io 中使用 options.query?