使用Node.js进行IPv6组播

Bra*_*rad 10 multicast ipv6 node.js

我正在通过VPN试验IPv6 UDP组播.我试过以下代码:

const dgram = require('dgram');

let sock = dgram.createSocket('udp6', {
  reuseAddr: true
});

sock.on('message', (data, source) => {
  console.log('on message', arguments);
});

sock.bind('36912', '2620:9b::1944:e598', () => {
  sock.addMembership('ff02::1:3', '2620:9b::1944:e598');
});


setInterval(() => {
  let buf = Buffer.from((new Date()).toString());
  sock.send(buf, 0, buf.length, 36912, 'ff02::1:3');
}, 500);
Run Code Online (Sandbox Code Playgroud)

该脚本运行,我看到使用Wireshark发送/接收的数据包,但两端都没有在控制台中显示它们.

Wireshark UDP Capture

我究竟做错了什么?有什么方法可以通过IPv6发送和接收基本多播?

los*_*der 7

范围ID - >接口号

在IPv6中,存在一个地址的scope_id的概念,该地址应该指示IP地址的上下文,并且通常仅表示它可以在哪个接口上访问.虽然范围具有特定于操作系统的名称,但每个范围仅转换为接口编号,0通常表示系统的默认值.

在IPv6多播中,此scope_id直接提供给IP_ADD_MEMBERSHIP和IP_MULTICAST_IF,而不是像IPv4那样提供与接口关联的ip.

包装器平滑v6的差异

node(通过libuv)addMembership通过从您提供的"接口地址"中查找scope_id来为您隐藏这种差异.

不幸的是,从一个IP开始并获得一个范围并没有多大意义(范围的重点是IP可以在不同的范围内有不同的用途.)因此libuv只能填写一个范围,如果您使用%[scope]格式明确地在地址的末尾提供它.

使用具有显式范围的地址

解决这个问题的方法似乎是:

 sock.bind('36912', '::', () => {
   sock.addMembership('ff02::1:3', '::%eth2');
 ...
 sock.send(buf, 0, buf.length, 36912, 'ff02::1:3%eth2');
Run Code Online (Sandbox Code Playgroud)

哪里:

  • ::在绑定中使用(或没有地址)是必要的,因为你要组合接收,这将过滤多播地址与需要普通地址的发送.

  • 使用%[iface#]强制此接口的范围#.

  • addMembership的第二个参数实际上可以从任何地址开始,因为我们强制范围,其余的被丢弃.

  • 通常,发送套接字是分开的,并且给定一个不同的端口或匿名端口,因为您要么可以配置,要么因为套接字太相似而有获得EADDRINUSE错误的危险.