Ryan Spicer Ryan Spicer - 2 months ago 20
Javascript Question

Node UDP dgram sending too many packets in recursive function

Having a tricky problem with the code I'm currently working on. Basically, the purpose of this code is to send a UDP broadcast, listen for a response (that isn't the broadcast it just sent), and connect via socket.io. The recursion is there to ensure that packets keep being sent, on a 1 second interval, until a response is given. Here's the meat of the code:

function requestBroadcast(message, broadcastPort) {
var client = dgram.createSocket('udp4');
client.bind(config.listenPort, function() {
client.setBroadcast(true);
})
var receivedResponse = false;

function checkResponse () {
if (receivedResponse) {
client.close();
return;
} else {
console.error("!");
client.send(message, 0, message.length, config.listenPort, config.broadcastAdd);
client.on('message', function(msg, rinfo) {
var msgObj = JSON.parse(msg);
console.error(msgObj);
if (!(msgObj.hasOwnProperty("KartNo"))) {
receivedResponse = true;
var socket = ioclient.connect("http://" + msgObj.address.toString() + ":" + msgObj.port.toString())
}
})
setTimeout(checkResponse, 1000);
}
}
checkResponse();
}

var msgObj = {KartNo: 38};
var msgObjStr = JSON.stringify(msgObj);
requestBroadcast(msgObjStr, 6000);


Unfortunately, the problem is this: each iteration of the recursive function, an additional packet is being sent. For example, this is what the terminal shows. Note the "!" after each call - the recursive function is only being called once each iteration, so that isn't the problem.

!
{ KartNo: 38 }
!
{ KartNo: 38 }
{ KartNo: 38 }
!
{ KartNo: 38 }
{ KartNo: 38 }
{ KartNo: 38 }
!
{ KartNo: 38 }
{ KartNo: 38 }
{ KartNo: 38 }
{ KartNo: 38 }


My only conclusion is that this has to be something to do with the dgram module itself, but I can't for the life of me figure out what.

That's all! Any help would be hugely appreciated, and feel free to ask me any questions about the code and its functionality. Cheers!

Answer

The problem is that you're adding a new message event listener every time you send a message (client.on('message', ...)). Instead, just add a message event listener once after calling .bind():

var client = dgram.createSocket('udp4');
client.bind(config.listenPort, function() {
    client.setBroadcast(true);
})
client.on('message', function(msg, rinfo) {
  var msgObj = JSON.parse(msg);
  console.error(msgObj);
  if (!(msgObj.hasOwnProperty("KartNo"))) {
    receivedResponse = true;
    var socket = ioclient.connect("http://" + msgObj.address.toString() + ":" + msgObj.port.toString())
  }
})
var receivedResponse = false;

function checkResponse () {
    if (receivedResponse) {
        client.close();
        return;
    } else {
        console.error("!");
        client.send(message, 0, message.length, config.listenPort, config.broadcastAdd);
        setTimeout(checkResponse, 1000);
    }
}