Socket.IO的Emit被发射到所有客户端
所以我在写一个的NodeJS应用程序,并作序,我的问题,请理解我的设置目前是如何工作的:Socket.IO的Emit被发射到所有客户端
我有谁通过Socket.io连接的客户端“服务器X“,然后我的”服务器X“通过Socket.io连接到”服务器Y“,它们都通过Socket.io将数据发回给对方。
客户< --->服务器X < --->服务器Ÿ
客户端是指用户和他们的浏览器,然后我有我的服务器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采取通过服务器Ÿ发出的价值,只是其发回给原来的客户端,或网页浏览器。但出于某种原因,该线路发射给所有连接的客户端。
我有一台笔记本电脑,这台电脑和我的手机都在测试这个,每次发生这种情况都会发送给所有人。
如果有人可以请帮助我,我将不胜感激。如果我需要发布更多的代码,请让我知道。
因为你已经安装了一个单独的侦听器的每个插座用于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
消息您会收到它,但是如果两个客户端同时登录并因此同时拥有监听器,则会导致竞争状况,然后第一条消息将被两个监听器接收。
我不确定你的代码。但我通常使用空间来发送给用户和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'})
我尝试了类似的东西,但它不完全是我在找的东西。我很欣赏愿意帮助,虽然:) – flakeyjake
你解决了我的问题,但我仍然困惑。为什么要从该tempData对象中删除套接字ID?你说在评论中删除ID值的数据副本,所以我们不会发送到客户端,但你不想知道他们是什么套接字ID?另外,我删除了'server_y.removeListener('return_login',fn)''这一行,因为它使得它只能尝试一次登录。 – flakeyjake
@flakeyjake - 客户端不需要知道服务器端连接的'socket.id',所以我想我会删除它以保持与之前发送给客户端的数据结构相同。我没有理由想把它发送给客户。如果您想避免将其移除,您可以允许将其发送给客户端 - 无损。我不知道你想要多次登录。是的,要做到这一点,您要么在发送登录信息时建立新的听众,要么不要删除它。 – jfriend00
@flakeyjake - 由于您看起来可能是新手,如果我的答案为您提供了解决方案,那么您可以通过单击答案左侧的绿色复选标记来向社区表明这一点。这也将为您遵循正确的程序赢得一些声望点。 – jfriend00