socket.io 没有发送给所有客户端

Posted

技术标签:

【中文标题】socket.io 没有发送给所有客户端【英文标题】:socket.io not emitting to all clients 【发布时间】:2017-08-17 17:48:51 【问题描述】:

我遇到了一个奇怪的问题——仅在我的生产环境中(在本地测试中一切正常)——socket.emit() 可以正常工作,但 io.emit() 不能。换句话说,每个单独的套接字客户端连接都可以向服务器发送和接收消息,但是当服务器向所有客户端发送消息时,它们都没有收到消息。这很奇怪,因为它可以看到所有客户端 - 如果我检查 Object.keys(io.engine.clients) 我会看到所有已连接客户端的 ID。但是 io.emit() 不会向其中任何一个广播。

我正在使用最新版本的节点(7.7.4 和 socket.io (1.7.3)。我在 Heroku 上托管,并启用了粘性会话。我使用集群以便利用所有 CPU,并且我设置了一个 redis 服务来同步所有工作人员。所有这些基础设施似乎都运行良好。

为什么 socket.emit() 对任何给定的套接字都有效,而其他方法都无效?

socket.on('sendChat', function(messageBundle) 
    console.log('sockets: ' + Object.keys(io.engine.clients)) //shows clients
    io.sockets.emit('incomingChat', messageBundle); //nothing
    io.emit('incomingChat', messageBundle); //also nothing
    var clients = Object.keys(io.engine.clients);
    for (var i = 0; i < clients.length; i++) 
        console.log('broadcasting to: ' + clients[i]);
        socket.broadcast.to(clients[i]).emit('incomingChat', messageBundle); //still nothing
    
    socket.emit('incomingChat', messageBundle); //this works though
);

更新:

这是我之前定义套接字的地方。

var redis = require('redis');
var pub = redis.createClient(redisPort, redisHost, 
    auth_pass: redisPwd
);
var sub = redis.createClient(redisPort, redisHost, 
    detect_buffers: true,
    auth_pass: redisPwd
);
var adapter = require('socket.io-redis');
io.adapter(adapter(
    pubClient: pub,
    subClient: sub
));

var cluster = require('cluster');
var WORKERS = process.env.WEB_CONCURRENCY || 3;
if (cluster.isMaster) 
    for (var i = 0; i < WORKERS; ++i)
        console.log('forking process ' + i);
    cluster.fork();
 else 
    var express = require('express');
    var session = require('express-session');
    var app = express();
    var server = require('http').createServer(app);
    var io = require('socket.io').listen(server);

    var port = process.env.PORT || 5000;
    server.listen(port, function() 
        console.log("Listening on " + port);
        console.log("testing");
    );

    var mySession = session(...) //this enables me to authenticate the socket using the same session middleware as the express routes

    io.use(function(socket, next) 
        mySession(socket.handshake, , next);
    );

    io.on('connection', function(socket) 
        socket.emit('welcome');
        console.log('socket connection');

        socket.on(... etc.)
   ...)
...)

在客户端,使用简单的配置启动套接字连接:

var socket = io(
    reconnection: true,
    reconnectionDelay: 100,
);

【问题讨论】:

我无法重现您的问题,一切正常。你能显示更多的代码吗? 特别是你定义iosocket的地方 感谢 cmets - 我已经用 iosocket 定义的信息更新了问题。 【参考方案1】:

io一开始没有声明,然后你尝试在else语句中重新声明。

【讨论】:

【参考方案2】:

对我来说,问题是 socket.io 和 reddis-adapter 的版本不匹配(将 socket io 升级到 3.0.1,redis 适配器保持在 5.x.x) 升级适配6.0.1解决了

【讨论】:

以上是关于socket.io 没有发送给所有客户端的主要内容,如果未能解决你的问题,请参考以下文章

socket.io 仅向发送者发送数据包

发送公共消息,包括发送方 Socket.io

Socket.io 客户端调试?

如何将 socket.io 挂载到 fastapi 应用程序并向所有连接的客户端发送广播

socket.io 如何跨多个服务器发送消息?

如何将消息发送给除 rails/actioncable 中的发件人之外的所有客户端?