Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js Socket.IO Emit正在向所有客户端发送_Node.js_Sockets_Express_Callback_Socket.io - Fatal编程技术网

Node.js Socket.IO Emit正在向所有客户端发送

Node.js Socket.IO Emit正在向所有客户端发送,node.js,sockets,express,callback,socket.io,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('conne

因此,我正在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”向服务器x发出
return\u login
时,我希望服务器x获取服务器Y发出的值,然后将其发送回原始客户端或web浏览器。但由于某种原因,该线路会向所有连接的客户端发出信号

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


如果有人能帮我,我将不胜感激。如果我需要发布更多代码,请告诉我。

我不确定您的代码。但我通常使用room向用户发出socket的回调函数。这是我使用回调而不是返回登录事件的解决方案

io.on('connection',函数(socket){
socket.on('login',函数(数据,回调){
//使用回调而不是返回登录事件
服务器发出('login',数据,函数(responseData){
//将此插座作为name=user\u id放入房间
socket.join(responseData.user\u id);
//通过回调返回结果
回调(响应数据)
});
});
});
//如果需要,使用return\u登录事件发送到用户\u id

io.to(user_id).emit('return_login',{key:'ok'})
它正在发送到所有客户端,因为您为
return_login
消息的每个套接字安装了单独的侦听器。因此,当一个客户端登录并将
return\u login
消息发送回您的服务器时,对于每个看到该消息并将其转发到该套接字的套接字,您都有一个单独的侦听器。通过这种方式,它被发送到每个连接的套接字

解决此问题的一种方法是确保
return\u 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\u login
消息后,您可能会删除该消息的侦听器,但如果两个客户端同时登录,因此同时都有侦听器,则会导致竞争条件,然后两位听众都会收到第一条消息。

您解决了我的问题,但我仍然感到困惑。为什么要从tempData对象中删除套接字id?您在评论中说,删除id值后创建数据副本,这样我们就不会将其发送给客户端,但您不想知道它们是什么套接字id吗?此外,我删除了行
server\u y.removeListener('return\u login',fn)
因为它使您只能尝试一次登录。@flakeyjake-客户端不需要知道服务器端连接的
socket.id
,所以我想我应该删除它,以保持与您以前发送给客户端的数据结构相同。我看这里没有理由想把它发送给客户。如果您想避免删除它,您可以允许将其发送给客户机-没有伤害。我不知道你想登录不止一次。是的,要做到这一点,您可以在发送登录消息时建立一个新的侦听器,也可以不删除它。@flakeyjake-因为这里看起来您可能是新来的,如果我的答案为您提供了一个解决方案,那么您可以通过单击答案左侧的绿色复选标记向社区表明这一点。这也会让你在这里因为遵循正确的程序而获得一些声誉积分。这更有意义@jfriend00,非常感谢你的帮助!我现在会把这个标记为答案,我尝试过类似的方法,但是它并不完全是我想要的。不过,我很感激你愿意帮忙:)