【问题标题】:Socket.IO clients to receive offline messages when coming backSocket.IO 客户端在回来时接收离线消息
【发布时间】:2014-12-26 00:30:57
【问题描述】:

环境:

Nodejs+Socketio

问题:

  1. 客户端 A 和客户端 B 都连接到服务器;
  2. 客户端 B 离线;
  3. 客户端A向客户端B发送消息(客户端B仍然离线);
  4. 客户端 B 再次连接服务器;
  5. [问题]客户端B收不到A的消息;

服务器代码

var clients = {};
io.sockets.on('connection', function (socket) {
socket.on('online', function (data) {
    if (!clients[data.username]) {
        clients[data.username] = socket;
    }
    io.sockets.emit('message',  data.user + 'online now');
});
socket.on('say', function (data) {
    if (data.to == 'all') {
        io.sockets.emit('message', data.message);
    } else { //to specific client
        clients[data.to].emit('message', data.message);
    }
});
});

说明

客户端B首先连接到一个地方的服务器。在客户端B离线期间,客户端A向客户端B发送消息。然后客户端B再次连接到另一个地方的服务器,客户端B需要接收来自客户端的消息A. 如何让它发挥作用?

【问题讨论】:

  • IMO 没有办法仅使用套接字来实现这一点,为此您必须检查客户端 B 的状态并将离线消息保存到 DB 或某个套接字变量,然后将其推回客户端B 在线时
  • 感谢您的cmets,您知道如何检查客户端B的状态吗?我如何知道客户端B是在线还是离线?
  • 来自socket.on('disconnect', function(){})
  • 请发布您的客户端代码。
  • 谢谢Shawn,Ravi说得对,应该有DB来存储特定客户端对应的离线消息。

标签: javascript node.js sockets offline


【解决方案1】:

如果我考虑哪个数据库及其配置和客户端,我必须编写的代码量将相当大,以创建解决方案。您基本上必须将消息保存在数据库中。当消息进入时,您必须写入您的对话对象(或代表客户端之间聊天消息的任何内容)。

socket.on('say', function (data) {
    // pseudo code to save conversation
    // var conversation = db.getConversation();
    // conversation.addMessage(data.message);
    // conversation.save();
    if (data.to == 'all') {
        io.sockets.emit('message', data.message);
    } else { //to specific client
        clients[data.to].emit('message', data.message);
    }
});

然后,当客户端加入时,您必须从数据库中获取所有消息。

socket.on('online', function (data) {
    if (!clients[data.username]) {
        clients[data.username] = socket;
    }
    // pseudo code to get messages and display to user on first load
    // var conversation = db.getConversation();
    // var messages = conversation.getLast10Messages();
    // messages.forEach(function(message) { 
    //     clients[data.username].emit('message', message);
    // });
    io.sockets.emit('message',  data.user + 'online now');
});

【讨论】:

    【解决方案2】:

    使用像 RabbitMQ 这样的消息队列。每当消息来自套接字写入接收者的队列时,当接收者加入时,他将从队列中选择它。

    【讨论】:

    • 它不适用于订阅一个主题的多个客户端,因为第一个客户端的消息将出列,其余离线客户端将不会收到任何消息。
    【解决方案3】:

    您可以为每个用户指定一个唯一的 id 作为用户名,将其保存在服务器端,或者使用用户名,您还有客户端 id(套接字 id),然后将它们保存在一个对象中,现在对于每个用户,您都有一个包含(用户名或唯一 ID)和套接字 ID 的对象,现在可以在用户离线时轻松保存消息,然后将其发送给用户。 在发出每个事件之前,您可以在socket的已连接sockets对象中搜索socket id。如果socket id存在,则可以发出,否则,您仍然有用户名,您可以通过用户名将消息保存到数据库中。

    请记住,您必须在客户端的每次发射中发送接收者对象信息(用户名或唯一 id 和套接字 id)

    【讨论】:

    • 这是一个很好的答案。我对另一个主题有一个额外的问题。我应该先将每条消息保存在数据库中(为了保持消息历史记录),然后再将消息发送给相应的用户,还是使用任何代理来降低发送时间?在传统的消息应用程序中,我不知道使用的是哪个流。
    猜你喜欢
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2015-01-16
    • 1970-01-01
    • 2020-02-01
    • 2012-04-07
    相关资源
    最近更新 更多