【问题标题】:Send Broadcast datagram发送广播数据报
【发布时间】:2011-05-30 14:17:25
【问题描述】:

我需要向连接到我的网络的所有机器(服务器)发送广播数据报。

我正在使用 NodeJS 多播

客户

var dgram = require('dgram');
var message = new Buffer("Some bytes");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost");
// If I'm in the same machine 'localhost' works
// I need to do something 192.168.0.255 or 255.255.255
client.close();

服务器

 var dgram = require("dgram");

 var server = dgram.createSocket("udp4");

 server.on("message", function (msg, rinfo) {
   console.log("server got: " + msg + " from " +
     rinfo.address + ":" + rinfo.port);
 });

 server.on("listening", function () {
   var address = server.address();
   console.log("server listening " + address.address + ":" + address.port);
 });

 server.bind(41234);

谢谢。

【问题讨论】:

    标签: javascript node.js udp broadcast multicast


    【解决方案1】:

    我花了很多时间尝试在计算机之间进行 UDP 广播和多播。希望这对其他人来说更容易,因为这个主题很难在网上找到答案。这些解决方案适用于 Node 版本 6.x-12.x:

    UDP 广播

    计算广播地址

    广播地址 = (~子网掩码) | (主机的 IP 地址) - 请参阅 Wikipedia。使用ipconfig(Windows) 或ifconfig(Linux),或查看netmask module

    服务器(记得把BROADCAST_ADDR改成正确的广播地址)

    var PORT = 6024;
    var BROADCAST_ADDR = "58.65.67.255";
    var dgram = require('dgram');
    var server = dgram.createSocket("udp4");
    
    server.bind(function() {
        server.setBroadcast(true);
        setInterval(broadcastNew, 3000);
    });
    
    function broadcastNew() {
        var message = Buffer.from("Broadcast message!");
        server.send(message, 0, message.length, PORT, BROADCAST_ADDR, function() {
            console.log("Sent '" + message + "'");
        });
    }
    

    客户

    var PORT = 6024;
    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.on('message', function (message, rinfo) {
        console.log('Message from: ' + rinfo.address + ':' + rinfo.port +' - ' + message);
    });
    
    client.bind(PORT);
    

    UDP 多播

    多播地址

    查看IPv4 Multicast Address Space RegistryRFC 2365 manual 第 6 节中更深入的说明,我们发现适当的本地范围多播地址为 239.255.0.0/16 和 239.192.0.0/14(即,除非您获得允许使用其他的)。

    下面的多播代码在具有这些地址的 Linux(和许多其他平台)上运行良好。

    大多数操作系统通过特定接口发送和侦听多播,默认情况下,如果有多个接口可用,它们通常会选择错误的接口,因此您永远不会在另一台机器上接收到多播(您只能在 localhost 上接收它们)。在Node.js docs 中阅读更多信息。要使代码可靠地工作,请更改代码,以便为您希望使用的接口指定主机的 IP 地址,如下所示:

    服务器 - server.bind(SRC_PORT, HOST_IP_ADDRESS, function() ...

    客户 - client.addMembership(MULTICAST_ADDR, HOST_IP_ADDRESS);

    查看以下支持来源:NodeJSJavaC# 和有用的command,以查看您订阅了哪些多播地址 - netsh interface ipv4 show joins

    服务器

    var SRC_PORT = 6025;
    var PORT = 6024;
    var MULTICAST_ADDR = '239.255.255.250';
    var dgram = require('dgram');
    var server = dgram.createSocket("udp4");
    
    server.bind(SRC_PORT, function () {         // Add the HOST_IP_ADDRESS for reliability
        setInterval(multicastNew, 4000);
    });
    
    function multicastNew() {
        var message = Buffer.from("Multicast message!");
        server.send(message, 0, message.length, PORT, MULTICAST_ADDR, function () {
            console.log("Sent '" + message + "'");
        });
    }
    

    客户

    var PORT = 6024;
    var MULTICAST_ADDR = '239.255.255.250';
    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.on('message', function (message, rinfo) {
        console.log('Message from: ' + rinfo.address + ':' + rinfo.port + ' - ' + message);
    });
    
    client.bind(PORT, function () {
        client.addMembership(MULTICAST_ADDR);   // Add the HOST_IP_ADDRESS for reliability
    });
    

    更新:server.sendadditional options(在文档中命名为 socket.send)。您可以为msg 使用字符串而不是缓冲区,并且根据您的版本,有几个参数是可选的。也可以检查回调函数是否发生错误。

    更新:自 Node.js v6 起,new Buffer(str) 已被弃用,取而代之的是 Buffer.from(str)。上面的代码已更新以反映此更改。如果您使用的是较早版本的 Node,请使用以前的语法。

    【讨论】:

    • 我有一个关于 UDP 多播的问题。您的示例运行良好,只有 1 个客户。但是,为了让更多的客户端从服务器接收多播消息,我们应该做些什么改变>?谢谢!
    • 抱歉回复晚了。对于多个客户端接收多播消息,您不需要做任何额外的事情。每个客户端只需订阅服务器发送消息的相同多播地址(使用addMembership 函数)。所有客户端都会收到消息(根据我的经验,成功率约为 99.9%,因为 UDP 并不完全可靠)。
    • 感谢您的回答。但在我的问题中,我的意思有所不同。我的目标是在同一台机器(Mac OS)上运行多个客户端,它们都是 MULTICAST_ADDR 的成员。这意味着所有客户端必须具有相同的 PORT 才能使多播工作。使用您的 UDP 多播代码,我需要以某种方式重用端口,以便能够多次运行 client.js。我设法在 dgram.createSocket(options[, callback]) 的文档中找到了一个选项 reuseAddr 字段,但找不到有关 PORT 的任何信息。如果您能提供这样的例子,我将不胜感激
    • 我找到了解决方案,很抱歉耽误您的时间。谢谢!解决方案(client = dgram.createSocket({ type: 'udp4', reuseAddr: true }); )
    • 嗨@Joseph238,好像我能够向多播组发送消息(使用tcpdump 检查),但连接到它的其他机器没有收到这些消息。两台机器位于不同的子网上,但路由器考虑了多播。你知道问题可能是什么吗?
    【解决方案2】:

    我从未使用过 Node.js,但我确实记得使用 Berkely 套接字(这似乎是使用最广泛的套接字实现)您需要启用 SO_BROADCAST 套接字选项才能将数据报发送到广播地址。查了dgram文档,好像有a function for it

    var client = dgram.createSocket("udp4");
    client.setBroadcast(true);
    client.send(message, 0, message.length, 41234, "192.168.0.255");
    

    您可能想以编程方式找出广播地址,但我无法帮助您。

    【讨论】:

    • 如果您使用 255.255.255.255,它将作为 RFC922 的本地广播地址。 =)
    • 很奇怪。即使进行了这种更改,服务器似乎也永远不会从客户端收到任何内容。
    • @Michael 您需要在 0.0.0.0 上收听,然后才能接收。
    • 这行不通,客户端必须在听:stackoverflow.com/questions/9242957/…
    【解决方案3】:

    我认为自从节点 0.10.0 以来,有些事情发生了变化,现在这对我有用:

    //var broadcastAddress = "127.255.255.255";
    var broadcastAddress = "192.168.0.255";
    
    var message = new Buffer("Some bytes");
    
    var client = dgram.createSocket("udp4");
    client.bind();
    client.on("listening", function () {
        client.setBroadcast(true);
        client.send(message, 0, message.length, 6623, broadcastAddress, function(err, bytes) {
            client.close();
        });
    });
    

    希望这对某人有所帮助;)

    【讨论】:

    • 非常感谢您,这让我发疯了。如果这有助于其他任何人进行故障排除——奇怪的是,只需简单地创建套接字并调用 send 就可以在 Windows 上正常工作。尝试在 Raspberry Pi OS 上运行相同的代码会抛出 EACCES 而不会沿着这条 bind / setBroadcast 路径。
    【解决方案4】:

    如果你想要一个自动广播地址,你可以这样做:

      const broadcastAddress = require('broadcast-address');
    
      const os = require("os")
    
      var PORT = 1234;
      var dgram = require('dgram');
      var server = dgram.createSocket("udp4");
    
      server.bind(function() {
          server.setBroadcast(true);
          setInterval(broadcastNew, 5000);
      });
    
      function broadcastNew() {
          var message = Buffer.from("Broadcast message!");
          Object.keys(os.networkInterfaces()).forEach(it=>{
            console.log(broadcastAddress(it));
            server.send(message, 0, message.length, PORT, broadcastAddress(it), function() {
              console.log("Sent '" + message + "'");
          });
          })
      }
    

    此代码将为您服务器上的每个接口获取一个广播地址并发送一条消息。

    ;) 保护

    注意:不要忘记安装broadcast-address = "npm i broadcast-address"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      相关资源
      最近更新 更多