【问题标题】:Socket used by socket.io events in a node.js servicenode.js 服务中的 socket.io 事件使用的套接字
【发布时间】:2014-06-20 21:04:04
【问题描述】:

恐怕这很难解释,老实说,我真的不能指望任何人经历这一切,但我不知道还能如何解释。

我似乎在将用户名链接到 node.js socket.io 服务中的套接字时遇到问题。我找到了一个相当标准的聊天示例,并根据我的需要对其进行了修改,并拥有

一直在尝试从 javascript 客户端测试其性能。客户端应用程序有一个用户界面,允许它指定要建立多少个连接,然后点击一个

按钮打开所有连接。当连接事件在客户端触发时,我会发送一个用户名(“用户”+连接号)并尝试在服务器上处理它。

在客户端中,我在连接时使用“强制新连接”选项,以便使用新连接而不是重新使用以前的连接。我这样做是为了允许

性能待测试。

我遇到的问题是服务器上使用的事件似乎有错误的套接字对象(最后一个连接的客户端)。我有点明白为什么会发生这种情况

异步原因,但我无法解决它。这是我的小型服务器应用程序:

var httpd = require('http').createServer();
var io = require('socket.io').listen(httpd);
io.sockets.on('connection', function (socket) {

    noOfConnections = noOfConnections + 1;
    console.log('SocketID ' + socket.id + ' connected. Connections = ' + noOfConnections);

    socket.on('login', function(UserName) {
        socket.set('UserName', UserName, function(err) {
            if (err) { throw err; }
            io.sockets.socket(socket.id).emit('serverMessage', 'SocketID (' + socket.id + ') Currently logged in as ' + UserName);
            console.log('SocketID (' + socket.id + ') ' + UserName + ' logged in. Connections = ' + noOfConnections);
        })
    });

});

httpd.listen(3000);
console.log("Server listening on port 3000");

var noOfConnections = 0;

客户端应用的相关部分如下:

    for (var index = 0; index < noOfConnections; index++) {
        var socket = io.connect('http://192.168.0.12:3000', { 'force new connection': true });

        socket.on('connect', function () {
            userNo = userNo + 1;

            addMessage("Socket connected Server SocketId = " + socket.socket.sessionid);

            var username = userNamePrefix + userNo
            socket.emit('login', username);
        });

    }
},

我将大量数据写入服务器控制台并将一些数据返回给客户端,以便它显示在客户端浏览器中。如果客户端建立 5 个连接,我会在服务器上看到这个

控制台:

Server listening on port 3000
SocketID i0M_578QQZcT0q9yraV_ connected. Connections = 1
SocketID 0c1l31sGy8sl1DkPraWA connected. Connections = 2
SocketID BEmhxokbfd95K-lGraWB connected. Connections = 3
SocketID i0UD5Prnkcu_o29araWC connected. Connections = 4
SocketID mbOSMts7JLCYlT6eraWD connected. Connections = 5
SocketID (mbOSMts7JLCYlT6eraWD) User1 logged in. Connections = 5
SocketID (mbOSMts7JLCYlT6eraWD) User2 logged in. Connections = 5
SocketID (mbOSMts7JLCYlT6eraWD) User3 logged in. Connections = 5
SocketID (mbOSMts7JLCYlT6eraWD) User4 logged in. Connections = 5
SocketID (mbOSMts7JLCYlT6eraWD) User5 logged in. Connections = 5

前 5 条连接消息中显示的 socket.id,看起来很棒!正如我所料,它们都不同。

客户端登录时下一条消息的 socketID 为每个登录的用户显示相同的(最后一个连接)socketID。这意味着我无法针对

设置用户名

套接字是因为用户名都与同一个套接字相关联。

客户端浏览器画面如下:

Socket connected Server SocketId = mbOSMts7JLCYlT6eraWD
Socket connected Server SocketId = mbOSMts7JLCYlT6eraWD
Socket connected Server SocketId = mbOSMts7JLCYlT6eraWD
Socket connected Server SocketId = mbOSMts7JLCYlT6eraWD
Socket connected Server SocketId = mbOSMts7JLCYlT6eraWD
SocketID (mbOSMts7JLCYlT6eraWD) Currently logged in as User1
SocketID (mbOSMts7JLCYlT6eraWD) Currently logged in as User2
SocketID (mbOSMts7JLCYlT6eraWD) Currently logged in as User3
SocketID (mbOSMts7JLCYlT6eraWD) Currently logged in as User4
SocketID (mbOSMts7JLCYlT6eraWD) Currently logged in as User5

前 5 条消息来自客户端套接字连接事件,并显示服务器套接字 ID 对于 5 个连接都相同。这意味着登录套接字不在

错误,但客户端的连接为最后一个套接字触发 5 次,而不是为每个客户端套接字触发一次。然后登录发生在

的那个套接字上

客户端,因此当它在那里触发时在服务器上是错误的。

那么有没有可能是服务器代码没有问题,而问题是我在客户端的 for 循环?这种类型的 for 循环在异步世界中是否,否?

非常欢迎任何建议或见解,因为我现在在这方面花了很长时间。

谢谢

【问题讨论】:

  • 这里有很多代码。如果您可以将其缩减为展示您遇到的问题所必需的,那么您将有更好的运气获得答案。
  • 谢谢。一个好点。我已经尽可能多地删除了显示问题所不需要的内容。

标签: javascript node.js sockets socket.io


【解决方案1】:

这是您客户端的问题。两个重要的点是只有函数在 javascript 中创建新的范围(具体来说,for 循环不会),以及 javascript 中的闭包的工作方式 - 它们捕获变量,而不是变量的内容。

所以,发生的事情是循环的每次迭代都使用相同的 socket 变量,但将其设置为不同的套接字,因此当循环结束时,一个 socket 变量包含最后创建的套接字。然后,一旦套接字的connected 事件触发,它们都会在同一个socket(最后一个)上发出。

您需要创建一个 IIFE,通过创建新范围来为每次循环运行分别捕获 socket 变量:

for (var index = 0; index < noOfConnections; index++) {
    (function(socket) {
        socket.on('connect', function () {
            userNo = userNo + 1;

            if (showDataMessages) {
                addMessage("Socket connected Server SocketId = " + socket.socket.sessionid);
            }

            var username = userNamePrefix + userNo
            socket.emit('login', username);
        });
    })(io.connect('http://192.168.0.12:3000', { 'force new connection': true }));
}

【讨论】:

  • 非常感谢您。它现在完美运行,我真的很高兴服务器端没问题,因为那是我一直在集中精力解决这个问题的地方。只有在这里写问题时,我才开始怀疑客户端,因为我添加了更集中的调试消息。我来自一个“老派”的 .net 世界,对 JavaScript 很陌生,不了解循环是如何工作的。您的解释对我帮助很大,表明我需要认真阅读 JavaScript 的工作原理。
猜你喜欢
  • 2022-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 2011-05-07
  • 2018-01-28
相关资源
最近更新 更多