如何发送多播消息并重用Erlang中的端口?
我的程序,我的第一个真正的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的实例的QUERY,注意它说的是端口: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多播有任何神秘的洞察力? 更新,以便我可以尝试并接受答案。 我想我不能这样做。
更新 :好的,我发现我认为是一个工作解决方案。 这似乎与加入多播组有关。
{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true},
{ip, Addr}, {add_membership, {Addr, IAddr}}]).
(当然,确保你没有运行可能进入冲突的DNS守护进程)
没有足够的代表回复emil的帖子下的{broadcast,true}讨论,抱歉。
SO_BROADCAST套接字标志(我假设映射到)必须设置或sendto(广播地址)将失败。 这是一项安全措施,可防止不想广播的节目发生滥用或错误。 否则,安全的程序将不得不尝试自己检查广播地址。
使SO_BROADCAST不会阻止您发送非广播数据包。 (再假设erlang的东西只是直接映射到setsockopts;我不知道erlang,只是联网!)
您可能想尝试strace来查看实际发生的系统调用。 查找socket(),然后发生该文件描述符。
你试图打开一个已经打开的套接字? 你不能使用相同的套接字发送和接收?
链接地址: http://www.djcxy.com/p/43577.html上一篇: How to send multicast messages and reuse a port in Erlang?