【问题标题】:websocket send to specific user nodejswebsocket发送到特定用户nodejs
【发布时间】:2020-01-23 10:22:46
【问题描述】:

我目前正在为移动前端创建一个 websocket 服务器。在某些情况下,我只需要将 json 发送给特定用户,经过多次尝试后,我仍然无法让 Websocket 正常工作,因此我可以一次将我的 json 发送给一个客户端。

我正在使用这个库:github.com/websockets/ws

为了解释我的问题,我有几个产品包含几个需要实时刷新的变量。当用户连接到产品时,他只会收到该产品的 json,而其他用户将收到他们当前使用的其他产品的 json。这就是为什么我想向用户发送一个特定的 json 来启用它

我想知道你们中是否有人知道如何解决这个问题,因为我开始阻止它。

非常感谢。

const opp = new WebSocket.Server({port: 10001});
let user = 0;
let lookup = [];

opp.on('connection', function connection(op) {
    lookup.push(op.id);
    let id = "";
    op.on('message', function incoming(message) {
        console.log('received: %s', message);
        id = message;
        query = {
            text: "SELECT id,state,users_list_name,user_win,timer_stamp FROM products WHERE id = " + parseInt(id) + " AND circle = 1 ORDER BY CASE WHEN state = \'available\' THEN \'1\' WHEN state = \'soon\' THEN \'2\' WHEN state = \'expired\' THEN \'3\' END",
        };
    });
    client.connect();
    const interval = setInterval(function ping() {
        client.query(query, (err, res) => {
            if (err) {
                console.log(err.toString());
                console.log(query);
            } else {
                console.log(lookup);
               for (let i = 0; i < lookup.length; i++){
                    console.log("########################");
                    lookup[i].send(JSON.stringify(res.rows));
                }
            }
        });
    }, 300);
});``` 

【问题讨论】:

  • 为什么你的标题说的是socket.io,但你的代码使用的是普通的webSocket?是哪个?
  • 这是一个错误,感谢您指出这一点。
  • 所以,lookup[i] 将成为来自op.idid。这真的是你可以发送的吗?您正在使用哪个 websocket 服务器模块,以便我可以查看它的 API?另外,您问题的第一句话仍然提到socket.io。我看到你已经更正了标题。
  • 如果您只想将数据发送到开始此时间间隔的客户端,那么不要循环遍历所有lookup 数组,只需执行op.send()。这将代表向您发送消息的客户端,该消息设置了与此间隔对应的查询。
  • 仅供参考,以 300 毫秒的频率为每个连接的 webSocket 运行单独的 setInterval() 根本不会扩展。您的数据库将很快成为瓶颈。我不知道您要在这里解决什么问题,但是您将需要一个不同/更好的架构,它不会让每个客户端每 300 毫秒单独访问您的数据库。

标签: node.js websocket


【解决方案1】:

好的。仍在尝试了解您所追求的实际规格。但是,假设以下情况(基于您对我之前问题的回答):

  1. 客户端使用 webSocket 进行连接。
  2. 当他们通过该 webSocket 发送消息时,该消息是 id 的内容,可以在您的数据库中查找并且他们希望定期更新。
  3. 该特定id 的更新应仅发送给请求它的特定客户端。
  4. 如果不同的客户端连接并指定了一些 id,他们应该只获得该 id 的更新。
  5. 当客户端发送指定不同id 的新消息时,他们的更新现在应该只针对该新id
  6. 一个客户端请求的id 的更新仅发送给该客户端(不发送给其他客户端)。

如果这是你真正想要的,这里有一种方法来构建它。

const wss = new WebSocket.Server({port: 10001});

// make database connection that all users share
client.connect();

wss.on('connection', function connection(ws) {
    // these variables are unique to each ws connection
    let interval, query;

    // when webSocket closes, stop any current interval timer associated with this webSocket
    ws.on('close', function() {
        if (interval) {
            clearInterval(interval);
        }
    });

    // when we get an id, start querying for updates on that id
    ws.on('message', function incoming(id) {
        console.log(`received: ${id}`);
        query = {
            text: "SELECT id,state,users_list_name,user_win,timer_stamp FROM products WHERE id = " + parseInt(id) + " AND circle = 1 ORDER BY CASE WHEN state = \'available\' THEN \'1\' WHEN state = \'soon\' THEN \'2\' WHEN state = \'expired\' THEN \'3\' END",
        };
        // if interval is not already going, start it
        if (!interval) {
            interval = setInterval(function() {
                client.query(query, (err, res) => {
                    if (err) {
                        console.log(err);
                        console.log(query);
                    } else {
                        // send data to just the one client that this timer is for
                        ws.send(JSON.stringify(res.rows));
                    }
                });
            }, 300);
        }
    });
});

现在,一些 cmets:

  1. 在很短的时间间隔内为每个客户端使用单独的轮询循环轮询数据库根本无法扩展。您将遇到严重的数据库规模问题。您确实需要更好的设计,但由于我们不知道您的应用程序的总体要求和架构,因此我们没有足够的信息来知道建议什么。可能您希望利用数据库中的通知来告诉您数据何时发生变化,而不是代表每个客户端在短时间内轮询它。

  2. 我找不到 lookup 数据结构的原因。您的 cmets 说您想将更新发送到一个特定的客户端,即请求该 ID 的客户端。这可以通过ws.send() 完成。

  3. 此代码假定client 变量表示与您的数据库的连接,每个连接的客户端的每个 setIntervals 都可以共享该连接。这就是该代码被移出wss.on('connection', ...) 事件处理程序的原因。

  4. 我改用更常见的术语 wss 来指代服务器实例,而使用ws 来指代特定连接客户端的 webSocket。

  5. ws.send() 是您发送到已连接客户端的方式。我仍然不知道你在用op.id 做什么。查看ws 库的文档,这似乎不是您可以用来发送的东西。

  6. 您的代码(和此代码)为每个连接的 webSocket 客户端创建一个单独的 setInterval() 计时器,并且它使用非常短的间隔时间。这不会扩展。在最坏的情况下,间隔时间需要延长到几秒(取决于所需的目标规模)。充其量,您需要完全停止轮询数据库并使用数据库中的其他机制来在数据更改时获取通知。

【讨论】:

  • 这正是我想要做的,感谢您花在上面的时间。我是nodejs的新手,所以也许我的回答不是最准确的,对此感到抱歉。谢谢
猜你喜欢
  • 1970-01-01
  • 2020-05-06
  • 2017-09-08
  • 2016-02-16
  • 2014-04-17
  • 1970-01-01
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多