I have the following code:
var dgram = require("dgram");
var start = 27015;
for(var i = start; i < (start + 100); i++)
{
var server = dgram.createSocket("udp4");
server.on("message", function(msg, sender) {
console.log(server.address().port)
});
server.bind(i);
}
Why it always output last port (27114) ?
What's wrong? I thought it would help identify the port of the receiving server.
Thank you.
Use a closure to capture the server for the callback:
server.on("message", (function (server) {
return function (msg, sender) {
console.log(server.address().port);
};
})(server));
And I'm not sure of how the on method works, but in normal JavaScript event handling, this refers to the object the event applies to. So you might be able to forget the closure and just use this.address().port to refer to the specific server that the event is happening to.
Another way to set it up is with:
server.on("message", getOnHandler(server));
function getOnHandler(s) {
return function (msg, sender) {
console.log(s.address().port);
};
}
Ian is on the right track - you need a closure. However, his way will cause a server dereference.
for(var i = start; i < (start + 100); i++) {
(function(port) {
var server = dgram.createSocket("udp4");
server.on("message", function(msg, sender) {
console.log(server.address().port)
});
server.bind(port);
})(i);
}
This will cause each server instance to be isolated within a closure but not dereferenced. They will keep existing, without being overwritten through scope issues.
You've fallen victim of variable hoisting and lexical scope.
Your code is equivalent to this:
var dgram = require("dgram");
var start = 27015;
var i;
var server;
for(i = start; i < (start + 100); i++)
{
server = dgram.createSocket("udp4");
server.on("message", function(msg, sender) {
console.log(server.address().port)
});
}
This means that server is always going to be the last assignment to server inside of the callback (well, technically it's going to be whatever value server points to when the callback is executed -- unless it's called during the binding though, it's always going to be the last one).
You can use a closure as Ian suggested, but I suspect that this will also be set to the server inside of the callback. (Or at least some way to access it. You'd have to check the docs.)