无法添加多播组
can't add multicast group
正在尝试为 ipv6 添加多播组,但出现 return 错误。不明白这个问题。使用 ipv4 它工作正常
(test_client@127.0.0.1)1> {ok, S} = gen_udp:open(3333, [binary, {active, false}, {ip, {65342,0,0,0,0,0,34048,9029}}, inet6, {multicast_loop, false}]).
{ok,#Port<0.1587>}
(test_client@127.0.0.1)4> inet:setopts(S, [{add_membership, {{65342,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}}]).
{error,einval}
不幸的是,这个主题在 erlang 文档中的记录很糟糕
也尝试过像 ff3c: , ff32:
这样的地址
更新
我查看了 Erlang/OTP 18.2 源代码,有使用函数 prim_inet:is_sockopt_val(add_membership, {{65280,0,0,0,0,0,34048,9029}, {0,0,0,0,0,0,0,0}})
它总是 return 错误,因为在 prim_inet:type_value_2/2 中我们有类型 ip,值 {_,_,_,_,_,_,_,_}
并且它只等待 ipv4 {_,_,_,_}
.
一方面我知道为什么打开套接字时不能添加 ipv6 成员,但另一方面打开问题
看起来 Erlang 的驱动程序没有实现 IPV6_ADD_MEMBERSHIP
,但它确实有原始支持,因此您可以自己构建它。这种方法的一个问题是您对通常在头文件中定义的内容进行硬编码,因此您的解决方案不会非常便携。
-module(unssmraw).
-export([test/0]).
test() ->
Port = 57100,
Mad = <<65340:16,0:16,0:16,0:16,0:16,0:16,34048:16,9029:16>>,
Ifindx = <<3:64/native>>,
Ip6 = 41,
Ip6am = 20,
{ok, Sock} = gen_udp:open(Port, [{reuseaddr,true}, inet6, binary]),
R3 = inet:setopts(Sock, [{raw, Ip6, Ip6am, <<Mad/binary, Ifindx/binary>> }]),
io:format("ssm ok? ~w ~n", [R3]),
receive
{udp, S, A, Pr, Pk} -> io:format("watcher sees: Socket ~p Address ~p Port ~p Packet ~p ~n", [S, A, Pr, Pk]) end.
示例测试发件人:
echo hi | socat - UDP6-SENDTO:\"ff3c::8500:2345\":57100
示例运行:
$ erl
Erlang/OTP 19 [erts-8.0.1] [source-761e467] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.0.1 (abort with ^G)
1> unssmraw:test().
ssm ok? ok
watcher sees: Socket #Port<0.453> Address {65152,0,0,0,47734,16383,65066,
19977} Port 43511 Packet <<"hi\n">>
ok
关于我的硬编码值的注释
如何找到Ifindx
中使用的接口索引:
截至 OTP 22 net:if_name2index is available to call. A language neutral description is here。我使用了 64 位,因为这是我系统上一个 int 的大小,它是我 in6.h 中 mreq 中的一个 int。)
Ip6
的值来自in.h
Ip6am
是 IPV6_ADD_MEMBERSHIP 来自 in6.h.
正在尝试为 ipv6 添加多播组,但出现 return 错误。不明白这个问题。使用 ipv4 它工作正常
(test_client@127.0.0.1)1> {ok, S} = gen_udp:open(3333, [binary, {active, false}, {ip, {65342,0,0,0,0,0,34048,9029}}, inet6, {multicast_loop, false}]).
{ok,#Port<0.1587>}
(test_client@127.0.0.1)4> inet:setopts(S, [{add_membership, {{65342,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}}]).
{error,einval}
不幸的是,这个主题在 erlang 文档中的记录很糟糕
也尝试过像 ff3c: , ff32:
这样的地址更新
我查看了 Erlang/OTP 18.2 源代码,有使用函数 prim_inet:is_sockopt_val(add_membership, {{65280,0,0,0,0,0,34048,9029}, {0,0,0,0,0,0,0,0}})
它总是 return 错误,因为在 prim_inet:type_value_2/2 中我们有类型 ip,值 {_,_,_,_,_,_,_,_}
并且它只等待 ipv4 {_,_,_,_}
.
一方面我知道为什么打开套接字时不能添加 ipv6 成员,但另一方面打开问题
看起来 Erlang 的驱动程序没有实现 IPV6_ADD_MEMBERSHIP
,但它确实有原始支持,因此您可以自己构建它。这种方法的一个问题是您对通常在头文件中定义的内容进行硬编码,因此您的解决方案不会非常便携。
-module(unssmraw).
-export([test/0]).
test() ->
Port = 57100,
Mad = <<65340:16,0:16,0:16,0:16,0:16,0:16,34048:16,9029:16>>,
Ifindx = <<3:64/native>>,
Ip6 = 41,
Ip6am = 20,
{ok, Sock} = gen_udp:open(Port, [{reuseaddr,true}, inet6, binary]),
R3 = inet:setopts(Sock, [{raw, Ip6, Ip6am, <<Mad/binary, Ifindx/binary>> }]),
io:format("ssm ok? ~w ~n", [R3]),
receive
{udp, S, A, Pr, Pk} -> io:format("watcher sees: Socket ~p Address ~p Port ~p Packet ~p ~n", [S, A, Pr, Pk]) end.
示例测试发件人:
echo hi | socat - UDP6-SENDTO:\"ff3c::8500:2345\":57100
示例运行:
$ erl
Erlang/OTP 19 [erts-8.0.1] [source-761e467] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.0.1 (abort with ^G)
1> unssmraw:test().
ssm ok? ok
watcher sees: Socket #Port<0.453> Address {65152,0,0,0,47734,16383,65066,
19977} Port 43511 Packet <<"hi\n">>
ok
关于我的硬编码值的注释
如何找到
Ifindx
中使用的接口索引:截至 OTP 22 net:if_name2index is available to call. A language neutral description is here。我使用了 64 位,因为这是我系统上一个 int 的大小,它是我 in6.h 中 mreq 中的一个 int。)
Ip6
的值来自in.hIp6am
是 IPV6_ADD_MEMBERSHIP 来自 in6.h.