Socket.IO Emit向所有客户端发送

时间:2017-06-20 01:23:34

标签: node.js sockets express callback socket.io

所以我在NodeJS中编写应用程序,并在前面提出我的问题,请理解我的设置目前是如何工作的:

我有客户通过Socket.io连接到"服务器X",然后我的"服务器X"通过Socket.io连接到"服务器Y",它们都通过Socket.io将数据发送回去。

客户< --->服务器X< --->服务器Y

客户端引用用户及其浏览器,然后我的服务器x​​和服务器y上都运行了一个节点应用程序。

因此,在我的服务器X下面的代码中,如果你看第4行,它的工作原理应该如此。它仅向请求它的客户发出消息。

io.on('connection', function(socket){

    // This works just fine.
    socket.emit('return_login', 'Test Message');

    socket.on('login', function(data){
        // This line correctly sends the data to Server Y
        server_y.emit('login', data);
    });

    server_y.on('return_login', function(data){
        // This emits to all connected clients???
        socket.emit('return_login', data);
    });

});

现在我的问题是"服务器Y"将return_login发送到服务器x,我想要发生的是服务器x获取服务器y发出的值,然后将其发送回原始客户端或Web浏览器。但由于某种原因,该线路将发送给所有连接的客户端。

我有一台笔记本电脑,这台电脑和我的手机都在测试这个,每次发光都会发送给每个人。

如果有人可以帮助我,我会非常感激。如果我需要发布更多代码,请告诉我。

2 个答案:

答案 0 :(得分:1)

我不确定你的代码。但我通常使用空间向用户发出和socket的回调函数。这是我使用回调而不是 return_login 事件

的解决方案

io.on('connection', function(socket){
    socket.on('login', function(data, callback){
        
        // Using callback instead of return_login event
        server_y.emit('login', data, function(responseData){
          
          // put this socket to room as name = user_id
          socket.join(responseData.user_id);
          
          // return result by callback
          callback(responseData)
        });
    });

});

// emit to exactly user_id with return_login event if you want
io.to(user_id).emit('return_login', {key: 'ok'})

答案 1 :(得分:0)

它正在向所有客户端发送,因为您已为return_login消息的每个套接字安装了单独的侦听器。因此,当一个客户端登录并且return_login消息被发送回您的服务器时,您为每个看到该消息的单个套接字都有一个单独的侦听器并将其转发到该套接字。通过这种方式,它将被发送到每个连接的套接字。

解决此问题的一种方法是确保return_login消息仅发送到它所属的套接字。如果您可以发送带有该消息的socket.id并让该服务器将该id作为响应的一部分回显,那么您可以在收到消息时检查该消息,以确保只将其发送到它所属的套接字。

这是基于纯消息的系统的问题之一。您正在尝试执行请求/响应,其中只有请求者看到响应,但socket.io不是请求/响应系统。响应将发送给该​​特定消息的所有侦听器,并且由于您为每个连接的单个插槽都有一个侦听器,每个插槽都会看到它,然后将其转发给它的客户端。

因此,通过对其他服务器进行相应的修改以回显id值,您可以这样做:

io.on('connection', function(socket){

    // This works just fine.
    socket.emit('return_login', 'Test Message');

    socket.on('login', function(data){
        // add our id so we can identify our response back
        data.id = socket.id;
        server_y.emit('login', data);
    });

    let fn = function(data) {
        // check to see if this message is destined for this socket
        if (data.id === socket.id) {
            // make data copy with id value removed so 
            //   we don't send that to the client
            let tempData = Object.assign({}, data);
            tempData.delete(id);
            socket.emit('return_login', tempData);
            // we're done with this listener so remove it
            server_y.removeListener('return_login', fn);
        }
    });

    server_y.on('return_login', fn);

});

在收到return_login消息之后删除你的监听器可能很诱人,但如果两个客户端同时正在同时登录,那么会导致竞争条件两者都有听众,然后两个听众都会收到第一条消息。