如何在Erlang中发送多播消息和重用端口?

如何在Erlang中发送多播消息和重用端口?,erlang,multicast,bonjour,zeroconf,Erlang,Multicast,Bonjour,Zeroconf,我的程序有了一个良好的开端,我的第一个真正的Erlang程序。 我让它听信息,读信息,分析信息。我也有它发送他们。 有一件事困扰着我,我不能发送端口5353,我已经尝试了一切。 我机器上的所有其他应用程序都可以通过端口5353、SubEthaEdit、iTunes和iChat进行监听和发送 解决方案必须在端口5353上广播发送,原因如下。 “如果收到的多播DNS查询中的源UDP端口不是端口 5353,这表示发起查询的客户端是 未完全实现所有多播DNS的简单客户端。 在这种情况下,多播DNS响应程

我的程序有了一个良好的开端,我的第一个真正的Erlang程序。 我让它听信息,读信息,分析信息。我也有它发送他们。 有一件事困扰着我,我不能发送端口5353,我已经尝试了一切。 我机器上的所有其他应用程序都可以通过端口5353、SubEthaEdit、iTunes和iChat进行监听和发送

解决方案必须在端口5353上广播发送,原因如下。

“如果收到的多播DNS查询中的源UDP端口不是端口 5353,这表示发起查询的客户端是 未完全实现所有多播DNS的简单客户端。 在这种情况下,多播DNS响应程序必须发送UDP响应 直接返回到客户端,通过单播,返回到查询数据包的 源IP地址和端口。此单播响应必须是 传统的单播响应,由传统的 单播DNS服务器;例如,它必须重复查询ID和 查询包中给出的问题。 "

发送多播消息时,它们都报告端口:5353。 我真的希望我的应用程序能玩得很好,并做同样的事情,发送端口5353。 这是我现在的模块

-module(zeroconf).

-include("zeroconf.hrl").

-export([open/0,start/0]).
-export([stop/1,receiver/0]).
-export([send/1]).

-define(ADDR, {224,0,0,251}).
-define(PORT, 5353).

send(Domain) ->
    {ok,S} = gen_udp:open(0,[{broadcast,true}]), % I really want this Port to be 5353 :-(
    % this doesn't complain or throw errors but it also doesn't work :-(        
    %{ok,S} = gen_udp:open(?PORT,[{reuseaddr,true}, {ip,?ADDR}, {broadcast,true},multicast_ttl,4}, {multicast_loop,false}, binary]),
    P = #dns_rec{header=#dns_header{},qdlist=[#dns_query{domain=Domain,type=ptr,class=in}]},
    gen_udp:send(S,?ADDR,?PORT,inet_dns:encode(P)),
    gen_udp:close(S).
下面是一些输出的样子

这是SubEthaEdit在本地网络上查找其他实例的查询,请注意,它显示端口:5353

From: {192,168,0,105}
Port: 5353
Data: {ok,{dns_rec,{dns_header,0,true,'query',true,false,false,false,false,0},
                   [],
                   [{dns_rr,"_see._tcp.local",ptr,in,0,0,
                            "jhr@Blackintosh._see._tcp.local",undefined,[],
                            false}],
                   [],[]}}
下面是我的模块中的一个查询,它在本地网络上查找iTunes的实例,注意它的端口是:59795 按照现在的代码,该端口是随机的。我真的希望是5353

From: {192,168,0,105}
Port: 59795
Data: {ok,{dns_rec,{dns_header,0,false,'query',false,false,false,false,false,
                               0},
                   [{dns_query,"_daap._tcp.local",ptr,in}],
                   [],[],[]}}

有人对UDP多播有任何神秘的见解吗?更新,以便我可以尝试接受答案。我想我就是做不到。你试着打开一个已经打开的插座吗?你不能用同一个插座发送和接收吗

更新:好的,我找到了我认为有效的解决方案。关键点似乎与加入多播组有关

  • 地址:多播组(例如{224,0,0,251}
  • IAddr是一个本地IP接口(例如,可以使用默认的{0,0,0})

  • (当然,请确保您运行的DNS守护程序可能会出现冲突)

    没有足够的代表来回复emil帖子下的{broadcast,true}讨论,抱歉

    必须设置SO_广播套接字标志(我假设映射到),否则发送到(广播地址)将失败。这是一个安全捕获,用于防止无意广播的节目被滥用或出错。否则,安全节目将不得不自己尝试检查广播地址

    启用SO_广播并不会阻止您发送非广播数据包。(再次假设erlang的东西直接映射到setsockopts;我不知道erlang,只是联网!)


    您可能希望尝试strace以查看实际发生的系统调用。查找socket(),然后查找该文件描述符发生的情况。

    我不这样认为,因为我需要传递{broadcast,true}选项以进行发送。无法更改{broadcast,true/false}当您发送消息时使用inet:setopts/2?我无法让它发送包含或不包含任何设置的消息周期。
    {ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true},
                                            {ip, Addr}, {add_membership, {Addr, IAddr}}]).