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. 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. 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
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! 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
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. 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. 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? Is this type of for loop a no, no in async World?
Any advice or insights are very welcome because I've spent a long time on this now.
Thanks