简体   繁体   English

node.js服务中socket.io事件使用的套接字

[英]Socket used by socket.io events in a node.js service

I'm afraid this is difficult to explain and to be honest, I can't really expect anyone to go through all of this but I don't know how else to explain it. 恐怕这很难解释,说实话,我真的不能期望任何人能经历所有这一切,但我不知道还有其他办法可以解释。

I seem to be having a problem linking usernames to sockets in a node.js socket.io service. 我似乎在将用户名链接到node.js socket.io服务中的套接字时遇到问题。 I took a fairly standard chat sample I found and modified it for my needs and have 我选择了一个相当标准的聊天示例,并根据需要对其进行了修改,

been trying to test its performance from a javascript client. 一直试图通过javascript客户端测试其性能。 The client app has a user interface to allow it to specify how many connections are to be made and then tap a 客户端应用程序具有一个用户界面,以允许其指定要建立的连接数,然后点击

button to open all the connections. 按钮打开所有连接。 When the connect event fires in the client I then send off a username ("User"+connection number) and attempt to handle this at the server. 当客户端触发连接事件时,我然后发送一个用户名(“用户” +连接号)并尝试在服务器上处理该用户名。

In the client, I am using the "force new connection" option when I connect so that a new connection is used rather than re-using previous connections. 在客户端中,我在连接时使用“强制新连接”选项,以便使用新连接而不是重复使用以前的连接。 I do this to allow 我这样做是为了

performance to be tested. 性能进行测试。

The problem I have is that the events used at the server seem to have the wrong socket object (the last client to have connected). 我的问题是,服务器上使用的事件似乎具有错误的套接字对象(已连接的最后一个客户端)。 I can kind of see why this might happen for 我可以看到为什么会发生这种情况

async reasons but I'm at a loss to solve it. 异步原因,但我无所适从。 Here is my small server app: 这是我的小型服务器应用程序:

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;

The relevant part of the client app is as follows: 客户端应用程序的相关部分如下:

    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);
        });

    }
},

I write lots of data to the server console and return some data to the client so it appears in the client browser. 我向服务器控制台写入了大量数据,并将一些数据返回给客户端,以便它们出现在客户端浏览器中。 If the client makes 5 connections, I see this at the server 如果客户端建立5个连接,我会在服务器上看到此连接

console: 安慰:

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

The socket.id shown in the first 5 connection messages, look great! 前5条连接消息中显示的socket.id看起来很棒! They are all different as I'd expect. 他们都是我所期望的不同。

The socketID for the next messages when the client logs in show the same (last connection) socketID for each user logging in. This means I can't set the username against the 客户端登录时,下一条消息的socketID对每个登录的用户显示相同的(上次连接)socketID。这意味着我无法针对

socket be cause the user names are then all associated with the same socket. 套接字,因为用户名然后都与同一个套接字关联。

The client browser screen is as follows: 客户端浏览器屏幕如下:

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

The first 5 messages are from the client socket connected event and show the server socketID to all be the same for the 5 connections. 前5条消息来自客户端套接字已连接事件,并且显示服务器socketID对于这5个连接都相同。 This implies the login socket is not at 这意味着登录套接字不在

fault but that the connection at the client fires 5 times for the last socket instead of once for each client socket. 故障,但客户端的连接为最后一个套接字触发5次,而不是为每个客户端套接字触发一次。 The login then takes place on that one socket at the 然后,登录会在

client and hence is wrong at the server when it fires there. 客户端,因此在服务器启动时在服务器上出错。

So is it possible the server code is not at fault and the problem is my for loop at the client? 那么服务器代码是否可能没有错误,问题出在客户端的我的for循环? Is this type of for loop a no, no in async World? 在异步世界中,这种类型的for循环是否为no,no?

Any advice or insights are very welcome because I've spent a long time on this now. 任何建议或见解都非常受欢迎,因为我已经花了很长时间了。

Thanks 谢谢

This is an issue in your client. 这是您客户的问题。 The two important points are that only functions create new scopes in javascript (specifically, for loops do not), and the way that closures in javascript work - they capture the variables, not the contents of the variables. 两个要点是,仅函数会在javascript中创建新作用域(特别是for循环不会创建新作用域),以及javascript中闭包的工作方式-它们捕获变量,而不捕获变量的内容。

So, what's happening is that each iteration of your loop is using the same socket variable but setting it to a different socket, so when the loops end the one socket variable contains the last socket created. 因此,发生的事情是循环的每次迭代都使用相同的socket变量,但将其设置为不同的套接字,因此,当循环结束时,一个socket变量包含最后创建的套接字。 Then, once the sockets' connected events fire, they all emit on the same socket (the last one). 然后,一旦套接字的connected事件触发,它们都会在同一socket (最后一个)上发出。

You'll want to create an IIFE to capture that socket variable separately for each run of the loop by creating new scopes: 您将要创建一个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 }));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM