NodeJS 数据报 - 接收 IPv6 多播

Posted

技术标签:

【中文标题】NodeJS 数据报 - 接收 IPv6 多播【英文标题】:NodeJS Datagram - Receive IPv6 multicast 【发布时间】:2014-01-17 10:33:02 【问题描述】:

我正在尝试在 node.js 中通过 IPv6 接收多播数据报。我在 IPv4 (udp4) 上以完全相同的方式执行此操作没有问题,但尝试对 udp6 执行相同操作会给我在 socket.addMembership 调用时出现 EINVAL 错误。这是我的代码:

var dgram = require('dgram');
var server = dgram.createSocket('udp6');

var PORT = 12345;
var MULTICAST_ADDRESS = 'ff7e:230::1234';

server.on('message', function (message, remote) 
    console.log('Message from: ' + remote.address + ':' + remote.port +' - ' + message);
);

server.on('listening', function () 
  var address = server.address();
  console.log('UDP listening on ' + address.address + ":" + address.port);
  server.addMembership(MULTICAST_ADDRESS);
);

server.bind(PORT);

这会导致:

    Error: addMembership EINVAL
            at new errnoException (dgram.js:454:11)
            at Socket.addMembership (dgram.js:396:11)
            at Socket.<anonymous> (/media/sf_projects/ipv6_multicast/server.js:57:10)
            at Socket.EventEmitter.emit (events.js:92:17)
            at startListening (dgram.js:141:10)
            at dgram.js:213:7
            at dns.js:72:18
            at process._tickCallback (node.js:415:13)
            at Function.Module.runMain (module.js:499:11)
            at startup (node.js:119:16)

当我注释掉server.addMembership(MULTICAST_ADDRESS); 时,套接字绑定成功,但没有收到任何数据报。

我尝试使用我的 IPv6 作为第二个参数调用 addMembership,但这也给出了 EINVAL。

server.addMembership(MULTICAST_ADDRESS,  'fe80::a00:27ff:fed1:cac9');

我也尝试将套接字绑定到特定接口:

server.bind(PORT, 'fe80::a00:27ff:fed1:cac9');

这也给了我绑定方法的 EINVAL。

这是我的 ifconfig 的输出:

    eth0      Link encap:Ethernet  HWaddr 08:00:27:d1:ca:c9  
                      inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
                      inet6 addr: fe80::a00:27ff:fed1:cac9/64 Scope:Link
                      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                      RX packets:8996 errors:0 dropped:0 overruns:0 frame:0
                      TX packets:6081 errors:0 dropped:0 overruns:0 carrier:0
                      collisions:0 txqueuelen:1000 
                      RX bytes:8389966 (8.3 MB)  TX bytes:510795 (510.7 KB)

    lo        Link encap:Local Loopback  
                      inet addr:127.0.0.1  Mask:255.0.0.0
                      inet6 addr: ::1/128 Scope:Host
                      UP LOOPBACK RUNNING  MTU:65536  Metric:1
                      RX packets:356 errors:0 dropped:0 overruns:0 frame:0
                      TX packets:356 errors:0 dropped:0 overruns:0 carrier:0
                      collisions:0 txqueuelen:0 
                      RX bytes:33534 (33.5 KB)  TX bytes:33534 (33.5 KB)

【问题讨论】:

我对你的多播地址有点困惑。 ff7e: 表示它是一个具有全局范围和嵌入式集合点地址的多播地址,但地址的其余部分与 RFC 3956 中定义的嵌入式集合点地址的模式不匹配。你能告诉我如何该地址已定义? 【参考方案1】:

如果您想绑定到本地链接 (fe80:) 地址,您必须指定 哪个 您想要的链接。不幸的是,我还没有找到一种方法来为 NodeJS 做到这一点。如果您绑定到全局 IPv6 地址,它将起作用。

对于多播支持,您似乎不走运...... NodeJS 似乎只支持 IPv4 多播。对addMembership 的调用实现为对uv_udp_set_membership 的调用,其中包含纯IPv4 代码。它使用inet_addr解析IP地址,使用IP_ADD_MEMBERSHIP选项调用setsockopt,而IPv6需要IPV6_ADD_MEMBERSHIP等。

NodeJS 的 IPv6 实现似乎有点落后:(

有兴趣的可以看这里的源码:https://github.com/joyent/node/blob/master/deps/uv/src/unix/udp.c

【讨论】:

谢谢。我想我会在 node.js 问题跟踪器上为此创建一个问题。我正在尝试不同的地址。 很高兴看到人们致力于 IPv6 支持!太糟糕了,NodeJS 还不如你 :) 我为此创建了问题:Need support for IPv6 Multicast in dgram @MichaelHampton 我在我的 Mac OS 机器上尝试了server.bind(PORT, 'fe80::...%en0');,但它不起作用,而使用server.bind(PORT, '2a00:8640:....'); 绑定到全球单播地址确实有效。我还没有查看内部结构,看看这个错误是否是 Mac OS 特有的......

以上是关于NodeJS 数据报 - 接收 IPv6 多播的主要内容,如果未能解决你的问题,请参考以下文章

单播广播组播多播

组播单播多播

单播多播(组播)和广播的区别

单播多播(组播)和广播的区别

单播多播(组播)和广播的区别,搞通信选整明白这三个东东

未使用 PYQT5 多播 UDP 接收数据报