erlang - 无法添加多播组

标签 erlang udp ipv6 multicast

尝试为 ipv6 添加多播组,但返回错误。不明白这个问题。使用 ipv4 可以正常工作

(<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b5c1d0c6c1ead6d9dcd0dbc1f58487829b859b859b84" rel="noreferrer noopener nofollow">[email protected]</a>)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>}

(<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f581908681aa96999c909b81b5c4c7c2dbc5dbc5dbc4" rel="noreferrer noopener nofollow">[email protected]</a>)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 源代码,有 using 函数 prim_inet:is_sockopt_val(add_membership, {{65280,0,0,0,0,0,34048,9029}, {0,0,0,0,0,0,0,0}})

它总是返回 false,因为在 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中使用的接口(interface)索引:

    截至 OTP 22 net:if_name2index可以调用。语言中立的描述是 here 。我使用了 64 位,因为这是我系统上 int 的大小,并且它是我的 in6.h 中 mreq 中的 int。)

  • Ip6的值来自in.h

  • Ip6am 是来自 in6.h 的 IPV6_ADD_MEMBERSHIP。

关于erlang - 无法添加多播组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38376640/

相关文章:

mysql - Erlang Emysql 准备好的查询和常规查询之间的编码差异

Erlang 编译器优化

java - 通过UDP数据包从matlab发送double到java

二郎:谁监督主管?

sockets - gen_tcp :recv/2 returns error, einval

c++ - 无法打开套接字类型为 SOCK_DGRAM 的 SCTP 套接字

network-programming - UDP sendto() 何时阻塞?

c++ - Qt5 中如何判断 QHostAddress 是 IPv4 还是 IPv6?

ios - 在基于本地 Mac 的 IPv6 DNS64/NAT64 网络中检查到 0.0.0.0 的可达性时不会发生错误

node.js - Socket.IO IPv6(2013 年 1 月版)