31

I'm trying to send a UDP Multicast Packet to: 230.185.192.108 so everyone subscribed will receive. A bit stuck. I believe it's broadcasting correctly, but can't seem to pick anything up with any client.

Server:

var news = [
   "Borussia Dortmund wins German championship",
   "Tornado warning for the Bay Area",
   "More rain for the weekend",
   "Android tablets take over the world",
   "iPad2 sold out",
   "Nation's rappers down to last two samples"
];

var dgram = require('dgram'); 
var server = dgram.createSocket("udp4"); 
server.bind();
server.setBroadcast(true)
server.setMulticastTTL(128);
server.addMembership('230.185.192.108'); 

setInterval(broadcastNew, 3000);

function broadcastNew() {
    var message = new Buffer(news[Math.floor(Math.random()*news.length)]);
    server.send(message, 0, message.length, 8088, "230.185.192.108");
    console.log("Sent " + message + " to the wire...");
    //server.close();
}

Client

var PORT = 8088;
var HOST = '192.168.0.102';
var dgram = require('dgram');
var client = dgram.createSocket('udp4');

client.on('listening', function () {
    var address = client.address();
    console.log('UDP Client listening on ' + address.address + ":" + address.port);
    client.setBroadcast(true)
    client.setMulticastTTL(128); 
    client.addMembership('230.185.192.108');
});

client.on('message', function (message, remote) {   
    console.log('A: Epic Command Received. Preparing Relay.');
    console.log('B: From: ' + remote.address + ':' + remote.port +' - ' + message);
});

client.bind(PORT, HOST);

References More info on NodeJS Datagram

Taurian
  • 1,660
  • 7
  • 20
  • 28
  • Works just fine for me. Perhaps firewall or routing issues? – mekwall Jan 03 '13 at 00:05
  • Hey Marcus, You're able to pickup the multicasted server messages after you subscribe to 230.185.192.108? – Taurian Jan 03 '13 at 00:12
  • Yep. I've only tried it locally on the same machine, but the client gets the messages. Edit: Could be worth noting that I used port 61088 instead of 8088 due to privileges. – mekwall Jan 03 '13 at 00:17
  • 1
    I changed the client.addMembership('230.185.192.108'); to client.addMembership('230.185.192.108','HOST'); and that seems to have done it. I'm doing everything locally too. Hey thanks again for the all the help there Marcus. – Taurian Jan 03 '13 at 01:02
  • 3
    Your title says multicast but your question says broadcast. Which is it? – user207421 Nov 20 '16 at 08:54
  • I found binding the listener to the multicast address - e.g. `client.bind(PORT, '230.185.192.108')` - worked. I did not need to specify HOST in the `addMembership()` call. (Running both processes on the same host, fwiw.) – broofa Apr 08 '20 at 13:49
  • Your "client" is bound to a host and port, listening for messages. Your "server" is initiating communication by sending original messages. These notions of client and server seem semantically reversed to me. – Wyck Mar 20 '21 at 00:30

3 Answers3

15

Changed:

client.addMembership('230.185.192.108');

to

client.addMembership('230.185.192.108',HOST); //Local IP Address
Taurian
  • 1,660
  • 7
  • 20
  • 28
  • how does that work? If the HOST is not specified, the OS should try to bind to *all* applicable interfaces, so by specifying only *one* HOST, we only restrict the interfaces that the OS will bind to, right? – Willem Mulder Oct 28 '14 at 08:05
  • 3
    If HOST is not specified, it picks one at random apparently: https://github.com/nodejs/node/pull/7244/files – Segfault Aug 31 '16 at 21:40
  • @WillemMulder You are thinking of TCP. UDP multicast doesn't work like that. This isn't a TCP bind, it s a UDP multicast group join. – user207421 Nov 20 '16 at 08:55
  • @EJP Yes it's UDP, and a group is usually joined on a specific interface (identified by setting the HOST variable). I was wondering how making the addMembership more restrictive would work to fix this issue, but Segfault pointed out that leaving out the HOST variable doesn't bind to all interfaces but to *one* interface at random. That's odd behaviour, and that's why specifying the HOST is fixing the problem because now the behaviour becomes predictable. – Willem Mulder Nov 21 '16 at 07:43
14

This answer is old, but shows up high on Google's search results. With Node v4.4.3, the server example fails with error EBADF. The complete working block of code is listed below:

Server:

//Multicast Server sending messages
var news = [
   "Borussia Dortmund wins German championship",
   "Tornado warning for the Bay Area",
   "More rain for the weekend",
   "Android tablets take over the world",
   "iPad2 sold out",
   "Nation's rappers down to last two samples"
];

var PORT = 41848;
var MCAST_ADDR = "230.185.192.108"; //not your IP and should be a Class D address, see http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
var dgram = require('dgram'); 
var server = dgram.createSocket("udp4"); 
server.bind(PORT, function(){
    server.setBroadcast(true);
    server.setMulticastTTL(128);
    server.addMembership(MCAST_ADDR);
});

setInterval(broadcastNew, 3000);

function broadcastNew() {
    var message = new Buffer(news[Math.floor(Math.random()*news.length)]);
    server.send(message, 0, message.length, PORT,MCAST_ADDR);
    console.log("Sent " + message + " to the wire...");
}

Client:

//Multicast Client receiving sent messages
var PORT = 41848;
var MCAST_ADDR = "230.185.192.108"; //same mcast address as Server
var HOST = '192.168.1.9'; //this is your own IP
var dgram = require('dgram');
var client = dgram.createSocket('udp4');

client.on('listening', function () {
    var address = client.address();
    console.log('UDP Client listening on ' + address.address + ":" + address.port);
    client.setBroadcast(true)
    client.setMulticastTTL(128); 
    client.addMembership(MCAST_ADDR);
});

client.on('message', function (message, remote) {   
    console.log('MCast Msg: From: ' + remote.address + ':' + remote.port +' - ' + message);
});

client.bind(PORT, HOST);

For the novices like me, client.bind(PORT,HOST); is the important bit. I couldn't get the client to receive anything when bound to HOST=127.0.0.1, but worked when the IP address was used. Again, HOST if excluded, the example won't work when testing using a single machine (client will throw EADDRINUSE error)

Abhijit Karnik
  • 167
  • 1
  • 8
  • 1
    Change `dgram.createSocket('udp4')` to `dgram.createSocket({ type: 'udp4', reuseAddr: true })` and you will be able to remove `HOST` variable and get rid of EADDRINUSE error on the single mahine. – Ilia Liachin Jan 28 '18 at 08:06
0

The solution provided here was not working for me, while this gist worked right out of the box: https://gist.github.com/ciaranj/9056285

I copied that here for convenience, all credits should go to @ciaranj.

client.js:

var PORT = 5007;
var dgram = require('dgram');
var client = dgram.createSocket({ type: 'udp4', reuseAddr: true })

client.on('listening', function () {
    var address = client.address();
    console.log('UDP Client listening on ' + address.address + ":" + address.port);
    client.setBroadcast(true)
    client.setMulticastTTL(128);
    client.addMembership('224.1.1.1');
});

client.on('message', function (message, remote) {
    console.log('A: Epic Command Received. Preparing Relay.');
    console.log('B: From: ' + remote.address + ':' + remote.port + ' - ' + message);
});

client.bind(PORT);

server.js:

var news = [
    "Borussia Dortmund wins German championship",
    "Tornado warning for the Bay Area",
    "More rain for the weekend",
    "Android tablets take over the world",
    "iPad2 sold out",
    "Nation's rappers down to last two samples"
];

var dgram = require('dgram');
var server = dgram.createSocket("udp4");
server.bind(function () {
    server.setBroadcast(true)
    server.setMulticastTTL(128);
    setInterval(broadcastNew, 3000);
});

function broadcastNew() {
    var message = new Buffer.from(news[Math.floor(Math.random() * news.length)]);
    server.send(message, 0, message.length, 5007, "224.1.1.1");
    console.log("Sent " + message + " to the wire...");
}
dirkk0
  • 2,460
  • 28
  • 34