我在 Fedora 上使用 netcat 来测试 IPv6 UDP 多播地址。命令是
echo hi | nc -6 -u ff02::777:777:777 7777
netcat 回应:“参数无效。”
运行 strace 产量
connect(3, {sa_family=AF_INET6, sin6_port=htons(7777), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "ff02::777:777:777", &sin6_addr), sin6_scope_id=0}, 28) = -1 EINVAL
运行类似的命令但没有 IPv6,
echo hi | nc -u 192.168.255.255 7777
工作得很好。
答案1
初步说明:您的 IPv4 网络未设置为 192.168.0.0/16,但很可能设置为 192.168.0.0/24 或任何其他 /24 范围:因此 192.168.255.255 不是广播,否则echo hi | nc -u 192.168.255.255 7777
会失败。对于广播,IPv6 不支持而仅支持 IPv4,应用程序必须使用SO_BROADCAST
套接字选项。这是通过-b
netcat 选项实现的。假设您实际上位于网络 192.168.0.0/24(而不是 /16)中,则为:
nc -b -u 192.168.0.255 7777
请注意,广播不是多播。
关于这个问题。整个ff02::/16
范围在链接本地多播范围。对于此范围,只有当接口与其关联时,地址才是完整的(这就是为什么它是一个关联- 本地范围)。此范围内的有效地址不能只是ff02::777:777:777
.假设 LAN 接口被称为eth0
,ff02::777:777:777%eth0
是一个有效地址,如定义在RFC 4007:
nc -6 -u ff02::777:777:777%eth0 7777
这可能是由库自动处理的,而不是由nc
命令本身处理的。使用不需要接口的作用域通常会失败,因为接口不应该是地址的一部分。
如果您不想必须需要该接口,请不要使用链接本地(或节点本地)范围。切换到 site-local: ff05 ,不需要指定接口即可工作:
nc -6 -u ff05::777:777:777 7777
在 Linux 上,可以通过以下命令看出这两个命令的区别ss
:
$ ss -aun dport == 7777
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 [2001:db8:900d:cafe:0:1:2:3]:58092 [ff05::777:777:777]:7777
ESTAB 0 0 [fe80::8c5f:87ff:fe50:d08a]%eth0:60937 [ff02::777:777:777]:7777
这里有一个全球地址以太网0并且它不是链接本地范围,该地址被选为源。对于链路本地范围地址,套接字绑定到接口。对于 Linux 情况,请参阅此 Q/A,了解与发送时(以及未使用IPV6_MULTICAST_IF
)接口选择相关的其他注意事项:如何设置首选 IPv6 接口
最后注意:您应该考虑切换到索卡特具有比网猫, 包括加入多播组对于 IPv4。虽然它支持 IPv6,但它并不直接支持 IPv6 多播,但可以使用任意setsockopt(2)
调用来实现不支持的功能,包括处理 IPv6 多播。这还是比网猫它只是不支持接收前一个发出的多播流量网猫命令。
所以与索卡特,这里是一个至少在具有 amd64 (x86_64) 架构的 Linux 上有效的示例,并且可能在其他 *nix 上工作,可能在更改下面的值 20 及其适当的替换(对于IPV6_ADD_MEMBERSHIP
/ IPV6_JOIN_GROUP
)之后,使用原始setsockopt(2)
选项来启用在索引为 2 的接口(之后的第一个接口罗),由第一个发送网猫命令:
socat udp6-recv:7777,setsockopt-listen=41:20:xff020000000000000000077707770777i2 -
该选项将使用以下命令进行解码strace
:
setsockopt(5, SOL_IPV6, IPV6_ADD_MEMBERSHIP, {inet_pton(AF_INET6, "ff02::777:777:777", &ipv6mr_multiaddr), ipv6mr_interface=if_nametoindex("eth0")}, 20) = 0
这里使用所谓的“dalan”格式来传递任意套接字选项ipv6_mreq结构:一个 IPv6 地址(x
对于任意十六进制值,这里是 16 字节的 IPv6 地址),后跟一个接口索引(i
对于整数)。